您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Some fixes for Youtube polymer engine
当前为
// ==UserScript== // @name Youtube polymer engine fixes // @description Some fixes for Youtube polymer engine // @namespace bo.gd.an[at]rambler.ru // @version 1.0.0 // @match https://www.youtube.com/* // @compatible firefox 56 // @author Bogudan // @grant none // @run-at document-end // ==/UserScript== //debug helper: //window.YTFixes = {}; (function() { 'use strict'; function gebi (id) { return document.getElementById (id); } // test local storage availability (required for settings saving) and load settings let settings = {}, ls; try { function lsTest (st, v) { st.setItem ('__fix_test__', v); return st.getItem ('__fix_test__') == v; }; let _s = window.localStorage; if (lsTest (_s, 'qwe') && lsTest (_s, 'rty')) { // do 2 times just in case LS stored value once, but does not let change it later ls = _s; settings = JSON.parse (ls.getItem ('__fix__settings__')) || {}; } } catch (e) { } // delete old settings if ("default_player_640" in settings) { settings.default_player = settings.default_player_640 ? 3 : 0; delete settings.default_player_640; } if ("reduce_thumbnail" in settings) { settings.thumbnail_size = settings.reduce_thumbnail ? 2 : 0; delete settings.reduce_thumbnail; } // set default values if (!("align_player" in settings)) settings.align_player = 0; if (!("default_player" in settings)) settings.default_player = 0; if (!("hide_guide" in settings)) settings.hide_guide = true; if (!("hide_yt_suggested_blocks" in settings)) settings.hide_yt_suggested_blocks = true; if (!("logo_target" in settings)) settings.logo_target = ""; if (!("reduce_font" in settings)) settings.reduce_font = true; if (!("theater_player" in settings)) settings.theater_player = 0; if (!("thumbnail_size" in settings)) settings.thumbnail_size = 2; if (!("thumbnail_size_m" in settings)) settings.thumbnail_size_m = 720; if (!("unfix_header" in settings)) settings.unfix_header = true; console.log ('fix settings:', settings); // catch "settings" page if (document.location.pathname == '/fix-settings') { document.title = "YouTube Polymer Fixes: Settings"; let plane = document.createElement ('div'), e1, e2; plane.className = 'ytfix'; let style = document.createElement ('style'); style.type = 'text/css'; style.innerHTML = [ '.ytfix{position:absolute;left:0;top:0;right:0;bottom:0;background:#eee;padding:3em}', '.ytfix_line{margin:1em}', '.ytfix_line span,.ytfix_line input,.ytfix_line select{margin-right:1em}', '.ytfix_field{padding:0.2em;border:1px solid #888}', '.ytfix_button{padding:0.4em;border:1px solid #888}', '.ytfix_hide{display:none}' ].join (''); plane.appendChild (style); function AddLine () { let q = document.createElement ('div'); q.className = 'ytfix_line'; for (let i = 0, L = arguments.length; i < L; ++i) q.appendChild (arguments [i]); plane.appendChild (q); return q; } e1 = document.createElement ('b'); e1.appendChild (document.createTextNode ('YouTube Polymer Fixes: Settings')); AddLine (e1); if (!ls) { e1 = document.createElement ('span'); e1.style = 'color:red'; e1.appendChild (document.createTextNode ('Cannot edit settings: no access to local storage.')); AddLine (e1); e1 = document.createElement ('span'); e1.appendChild (document.createTextNode ('If you are using Firefox, allow cookies for this site.')); AddLine (e1); } else { let ess = {}; function MakeDesc (desc) { let e = document.createElement ('span'); e.appendChild (document.createTextNode (desc)); return e; } function MakeBoolElement (nm) { let e = document.createElement ('input'); e.type = 'checkbox'; e.checked = settings [nm]; ess [nm] = e; return e; } function MakeListElement (nm, opts) { let e = document.createElement ('select'); e.className = 'ytfix_field'; ess [nm] = e; for (let i = 0, L = opts.length; i < L; ++i) { let o = document.createElement ('option'); o.appendChild (document.createTextNode (opts [i])); //if (i == val) // o.setAttribute ('selected', ''); e.appendChild (o); } e.selectedIndex = settings [nm]; return e; } function MakeTextElement (nm) { let e = document.createElement ('input'); e.className = 'ytfix_field'; e.value = settings [nm]; ess [nm] = e; return e; } AddLine (MakeBoolElement ("hide_guide"), MakeDesc ('Hide "Guide" menu when page opens')); AddLine (MakeBoolElement ("reduce_font"), MakeDesc ("Reduce font size in video descriptions")); let tsm = MakeTextElement ("thumbnail_size_m"); tsm.className = settings.thumbnail_size == 5 ? 'ytfix_field' : 'ytfix_hide'; let tsi = MakeListElement ("thumbnail_size", ['default', '180px', '240px', '360px', '480px', 'manual']); tsi.addEventListener ('change', function () { ess.thumbnail_size_m.className = ess.thumbnail_size.selectedIndex == 5 ? 'ytfix_field' : 'ytfix_hide'; }); AddLine (MakeDesc ('Set thumbnails size for front page'), tsi, tsm); AddLine (MakeDesc ("Set player size in default mode"), MakeListElement ("default_player", ['default', '256x144px', '426x240px', '640x360px', '853x480px', '1280x720px'])); AddLine (MakeDesc ("Set player size in theater mode"), MakeListElement ("theater_player", ['default', '256x144px', '426x240px', '640x360px', '853x480px', '1280x720px'])); AddLine (MakeBoolElement ("hide_yt_suggested_blocks"), MakeDesc ('Hide YouTube suggestions blocks like "Recommended playlists" or "Latest YouTube posts"')); AddLine (MakeBoolElement ("unfix_header"), MakeDesc ("Unstick header bar from top of the screen")); AddLine (MakeDesc ("Align resized player into it's container (normal and theater modes)"), MakeListElement ("align_player", ['center', 'left', 'right'])); AddLine (MakeDesc ("Change YT logo target to https://www.youtube.com/..."), MakeTextElement ("logo_target")); e1 = document.createElement ('input'); e1.type = 'button'; e1.className = 'ytfix_button'; e1.value = 'Save settings and return to YouTube'; e1.addEventListener ('click', function () { settings.hide_guide = ess.hide_guide.checked; settings.reduce_font = ess.reduce_font.checked; settings.thumbnail_size = ess.thumbnail_size.selectedIndex; if (settings.thumbnail_size == 5) { let v = ess.thumbnail_size_m.value; if (!/^\d+$/.test (v)) { alert ('Error: invalid value for thumbnails size'); return; } settings.thumbnail_size_m = parseInt (v); } settings.default_player = ess.default_player.selectedIndex; settings.theater_player = ess.theater_player.selectedIndex; settings.hide_yt_suggested_blocks = ess.hide_yt_suggested_blocks.checked; settings.unfix_header = ess.unfix_header.checked; settings.align_player = ess.align_player.selectedIndex; settings.logo_target = ess.logo_target.value; ls.setItem ('__fix__settings__', JSON.stringify (settings)); alert ('Settings saved'); history.back (); }); e2 = document.createElement ('input'); e2.type = 'button'; e2.className = 'ytfix_button'; e2.value = 'Return to YouTube without saving'; e2.addEventListener ('click', function () { history.back (); }); AddLine (e1, e2); } document.body.appendChild (plane); return; } // apply settings let styles = [], intervals = []; function addInterval (period, func, params) { if (!period) period = 1; intervals.push ({ cnt: period, period: period, call: func, params: params || [] }); } if (settings.hide_guide) { let guide_button = gebi ('guide-button'); if (guide_button) { let tmp = guide_button.getElementsByTagName ('button'); if (tmp.length) { tmp = tmp [0].attributes; if (tmp && tmp ['aria-pressed'].value == 'true') guide_button.click (); } } // old engine: if (gebi ('appbar-guide-button')) document.documentElement.classList.remove ('show-guide'); } if (settings.reduce_font) { styles.push ('#video-title.ytd-rich-grid-video-renderer,#text.ytd-channel-name,#metadata-line.ytd-video-meta-block{font-size:14px!important;line-height:1.2em!important}'); // fix: "not interested" placeholder bigger than original element by about 40% styles.push ('paper-button.style-blue-text{padding:0!important}'); } if (settings.thumbnail_size) styles.push ('ytd-rich-item-renderer{width:' + [0, 180, 240, 360, 480, settings.thumbnail_size_m] [settings.thumbnail_size] + 'px!important}'); if (settings.hide_yt_suggested_blocks) styles.push ('div#contents.ytd-rich-grid-renderer ytd-rich-section-renderer{display:none!important}'); if (settings.unfix_header) styles.push ('div#masthead-container.ytd-app,ytd-mini-guide-renderer.ytd-app,ytd-feed-filter-chip-bar-renderer,app-drawer#guide{position:absolute!important}'); styles.push ([ '#player-theater-container{margin-left:auto!important;margin-right:auto!important}', '#player-container-outer{margin-left:0!important}', '#player-container-outer{margin-right:0!important}#player-theater-container{margin-left:auto!important}', ] [settings.align_player]); const sizes = [undefined, { w: 256, h: 244 }, { w: 427, h: 240 }, { w: 640, h: 360 }, { w: 854, h: 480 }, { w: 1280, h: 720 }]; let size_norm = sizes [settings.default_player]; if (size_norm) styles.push ('#player-container-outer{min-width:' + size_norm.w + 'px!important;max-width:' + size_norm.w + 'px!important}'); let size_theater = sizes [settings.theater_player]; if (size_theater) styles.push ('#player-theater-container{min-width:' + size_theater.w + 'px!important;max-width:' + size_theater.w + 'px!important;max-height:' + size_theater.h + 'px!important}'); if (size_norm || size_theater) addInterval (1, function (sn, st) { let eq = document.getElementsByTagName ("ytd-watch-flexy"); if (!eq.length) return; let s = eq [0].hasAttribute ('theater') ? st : sn; if (!s) return; let ep = document.getElementById ("movie_player"); if (ep && ep.setInternalSize && ep.isFullscreen && !ep.isFullscreen () && ep.getPlayerSize && ep.getPlayerSize ().width != s [0]) ep.setInternalSize (s [0], s [1]); }, [size_norm, size_theater]); if (settings.logo_target) { let X = settings.logo_target; if (X [0] != '/') X = '/' + X; X = document.location.origin + X; addInterval (1, function (url) { let l = document.querySelectorAll ('a#logo'); for (let i = l.length; --i >= 0; ) if (l [i].href != url) { l [i].href = url; l [i].data.commandMetadata.webCommandMetadata.url = url; } }, [X]); } // "settings" button // can't store created button: Polymer overrides it's content on soft reload leaving tags in place // but can store element that Polymer does not know how to deal with and just drops let settingsButtonMark; function createSettingsButton () { if (settingsButtonMark && settingsButtonMark.parentNode) return; let toolBar = document.getElementsByTagName ('ytd-topbar-menu-button-renderer'); let _1st = toolBar [0]; if (!_1st) return; toolBar = _1st.parentNode; let sb = document.createElement ('ytd-topbar-menu-button-renderer'); sb.className = 'style-scope ytd-masthead style-default'; sb.setAttribute ('use-keyboard-focused', ''); sb.setAttribute ('is-icon-button', ''); sb.setAttribute ('has-no-text', ''); toolBar.insertBefore (sb, toolBar.childNodes [0]); let mark = document.createElement ('fix-settings-mark'); mark.style = 'display:none'; toolBar.insertBefore (mark, sb); // must be added to parent node of buttons in order to Polymer dropped it on soft reload let icb = document.createElement ('yt-icon-button'); icb.id = 'button'; icb.className = 'style-scope ytd-topbar-menu-button-renderer style-default'; let aa = document.createElement ('a'); aa.className = 'yt-simple-endpoint style-scope ytd-topbar-menu-button-renderer'; aa.setAttribute ('tabindex', '-1'); aa.href = '/fix-settings'; aa.appendChild (icb); sb.getElementsByTagName ('div') [0].appendChild (aa); // created by YT scripts let bb = icb.getElementsByTagName ('button') [0]; // created by YT scripts bb.setAttribute ('aria-label', 'fixes settings'); let ic = document.createElement ('yt-icon'); ic.className = 'style-scope ytd-topbar-menu-button-renderer'; bb.appendChild (ic); let gpath = document.createElementNS ('http://www.w3.org/2000/svg', 'path'); gpath.className.baseVal = 'style-scope yt-icon'; gpath.setAttribute ('d', 'M1 20l6-6h2l11-11v-1l2-1 1 1-1 2h-1l-11 11v2l-6 6h-1l-2-2zM13 15l2-2 8 8v1l-1 1h-1zM9 11l2-2-2-2 1.5-3-3-3h-2l3 3-1.5 3-3 1.5-3-3v2l3 3 3-1.5z'); let svgg = document.createElementNS ('http://www.w3.org/2000/svg', 'g'); svgg.className.baseVal = 'style-scope yt-icon'; svgg.appendChild (gpath); let svg = document.createElementNS ('http://www.w3.org/2000/svg', 'svg'); svg.className.baseVal = 'style-scope yt-icon'; svg.setAttributeNS (null, 'viewBox', '0 0 24 24'); svg.setAttributeNS (null, 'preserveAspectRatio', 'xMidYMid meet'); svg.setAttribute ('focusable', 'false'); svg.setAttribute ('style', 'pointer-events: none; display: block; width: 100%; height: 100%;'); svg.appendChild (svgg); ic.appendChild (svg); // YT clears *ic settingsButtonMark = mark; } addInterval (1, createSettingsButton, []); // styles addInterval (1, function () { if (styles.length == 0 || !document.body) return; let style_element = document.createElement ('style'); style_element.type = 'text/css'; style_element.innerHTML = styles.join (''); document.body.appendChild(style_element); styles = []; }, []); // intervals setInterval (function () { for (let i = intervals.length; --i >= 0; ) { let Q = intervals [i]; if (--Q.cnt > 0) continue; Q.call.apply (this, Q.params); Q.cnt = Q.period; } }, 1000); }) ();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址