Space-efficient Youtube

AKA: "Wide Youtube", AKA: "Wide video container" - Uses the page space on youtube more efficiently (especially good for high resolutions)

当前为 2022-02-03 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Space-efficient Youtube
  3. // @namespace 1N07
  4. // @author 1N07
  5. // @icon https://i.imgur.com/VgEiyi3.png
  6. // @icon64 https://i.imgur.com/VgEiyi3.png
  7. // @description AKA: "Wide Youtube", AKA: "Wide video container" - Uses the page space on youtube more efficiently (especially good for high resolutions)
  8. // @license unlicense
  9. // @include https://www.youtube.com/*
  10. // @version 2.3.6
  11. // @require https://openuserjs.org/src/libs/sizzle/GM_config.js
  12. // @grant GM_registerMenuCommand
  13. // @grant GM_unregisterMenuCommand
  14. // @grant GM_getValue
  15. // @grant GM_setValue
  16. // @noframes
  17. // ==/UserScript==
  18.  
  19. (function() {
  20. if(true)
  21. {
  22. var configCSS = `
  23. #SEYConfig {
  24. width: 320px !important;
  25. height: 685px !important;
  26. max-height: 100% !important;
  27. border: none !important;
  28. border-radius: 0 0 0 20px !important;
  29. box-shadow: black -1px 1px 20px;
  30. position: fixed !important;
  31. top: 0 !important;
  32. right: 0 !important;
  33. left: unset !important;
  34. background: #383838 !important;
  35. }
  36.  
  37. #SEYConfig_wrapper
  38. {
  39. padding: 10px;
  40. background-color: #212121;
  41. color: white;
  42. background-color: transparent;
  43. }
  44.  
  45. #SEYConfig .config_var
  46. {
  47. padding: 1px 20px;
  48. }
  49.  
  50. #SEYConfig input
  51. {
  52. background-color: #181818;
  53. color: white;
  54. border: none;
  55. float: left;
  56. margin-right: 5px;
  57. }
  58.  
  59. #SEYConfig input[type="text"]
  60. {
  61. width: 40px;
  62. text-align: center;
  63. }
  64.  
  65. #SEYConfig input[type="checkbox"]
  66. {
  67. filter: invert(90%);
  68. }
  69.  
  70. #SEYConfig .saveclose_buttons
  71. {
  72. background-color: #181818;
  73. color: white;
  74. border-color: gray;
  75. margin: 16px 5px 5px;
  76. }
  77.  
  78. #SEYConfig .section_header {
  79. background: #202020;
  80. margin-bottom: 5px;
  81. }
  82.  
  83. #SEYConfig .section_header_holder {
  84. margin-top: 8px;
  85. background-color: rgba(0,0,0,0.3);
  86. padding: 0 0 5px 0;
  87. border-radius: 0 0 10px 10px;
  88. }
  89.  
  90. #SEYConfig_resetLink { color: white !important; }
  91. `;
  92. }
  93.  
  94. var frame = document.createElement('div');
  95. frame.id = "SEYConf";
  96. document.body.appendChild(frame);
  97.  
  98. GM_config.init(
  99. {
  100. 'id': 'SEYConfig', // The id used for this instance of GM_config
  101. 'title': 'Space-efficient Youtube Config',
  102. 'fields': // Fields object
  103. {
  104. 'FPPCompOn': // This is the id of the field
  105. {
  106. 'section': 'Fade++',
  107. 'label': 'Fade++ compatibility mode', // Appears next to field
  108. 'type': 'checkbox', // Makes this setting a text field
  109. 'default': false // Default value if user doesn't change it
  110. },
  111.  
  112. 'HomeVideoContainerWidthEnabled':
  113. {
  114. 'section': 'Home page',
  115. 'label': 'Video container size mod enabled',
  116. 'title': 'Enables the video sizing modification below. This is disabled by default for now, due to a change in how YT renders videos on the home page. Might fix later. Enabling this will cause the video containers to be sized as set below, but the empty space is not properly used.',
  117. 'type': 'checkbox',
  118. 'default': false
  119. },
  120. 'HomeVideoContainerWidth':
  121. {
  122. 'label': 'Video container width',
  123. 'title': 'The width of the container which includes both the thumbnail and the title/other info',
  124. 'type': 'unsigned float',
  125. 'default': '360'
  126. },
  127. 'HideChannelIconNextToVideosOnHomePage':
  128. {
  129. 'label': 'Hide channel icon in video container',
  130. 'type': 'checkbox',
  131. 'default': false
  132. },
  133.  
  134. 'SubVideoContainerWidth':
  135. {
  136. 'section': 'Subscriptions page',
  137. 'label': 'Video container width',
  138. 'title': 'The width of the container which includes both the thumbnail and the title/other info',
  139. 'type': 'unsigned float',
  140. 'default': '210'
  141. },
  142.  
  143. 'TrendingVideoContainerWidth':
  144. {
  145. 'section': 'Trending page',
  146. 'label': 'Video container width',
  147. 'title': 'The width of the container which includes both the thumbnail and the title/other info',
  148. 'type': 'unsigned float',
  149. 'default': '600'
  150. },
  151. 'TrendingVideoContainerHeight':
  152. {
  153. 'label': 'Video container height',
  154. 'title': 'The height of the container. This directly affects thumnail size and how much space is left for the other info',
  155. 'type': 'unsigned float',
  156. 'default': '138'
  157. },
  158.  
  159. 'HQTN':
  160. {
  161. 'section': 'Subscriptions & Trending pages',
  162. 'label': 'Load high quality thumbnails',
  163. 'title': 'The default thumbnail resolution is fitted for the default video container size, so if you use defaults(or smaller) there is no need to enable this.',
  164. 'type': 'checkbox',
  165. 'default': false
  166. },
  167.  
  168. 'SearchVideoContainerWidth':
  169. {
  170. 'section': 'Search results page',
  171. 'label': 'Video container width',
  172. 'title': 'The width of the container which includes both the thumbnail and the title/other info',
  173. 'type': 'unsigned float',
  174. 'default': '600'
  175. },
  176. 'SearchVideoContainerHeight':
  177. {
  178. 'label': 'Video container height',
  179. 'title': 'The height of the container. This directly affects thumnail size and how much space is left for the other info',
  180. 'type': 'unsigned float',
  181. 'default': '150'
  182. },
  183. 'HideSearchVideoBadges':
  184. {
  185. 'label': 'Hide video badges',
  186. 'title': 'Hides the little badges like New/4K/CC etc. on the video containers leaving more space for the description',
  187. 'type': 'checkbox',
  188. 'default': false
  189. },
  190.  
  191. 'AutoExpandChannelVidContainers':
  192. {
  193. 'section': 'Channel pages',
  194. 'label': 'Auto-expand horizontal video lists',
  195. 'type': 'checkbox',
  196. 'default': false
  197. }
  198. },
  199. 'frame': frame,
  200. 'css': configCSS
  201. }
  202. );
  203.  
  204. var refreshAfterSave = false;
  205. GM_config.onOpen = function(doc, win, frame) {
  206. let saveBtn = frame.querySelector("#SEYConfig_saveBtn");
  207. let clone = saveBtn.cloneNode();
  208. clone.id = "SEYConfig_saveRefreshBtn";
  209. clone.textContent = "Save & Refresh";
  210. saveBtn.parentNode.insertBefore(clone, saveBtn);
  211. clone.onclick = function(){
  212. refreshAfterSave = true;
  213. saveBtn.click();
  214. };
  215. };
  216. GM_config.onSave = function(){
  217. if(refreshAfterSave)
  218. location.reload();
  219. };
  220.  
  221. var FPPCompOn = GM_config.get('FPPCompOn');
  222. var HomeVideoContainerWidthEnabled = GM_config.get('HomeVideoContainerWidthEnabled');
  223. var HomeVideoContainerWidth = CleanNumber(GM_config.get('HomeVideoContainerWidth'));
  224. var HideChannelIconNextToVideosOnHomePage = GM_config.get('HideChannelIconNextToVideosOnHomePage');
  225. var SubVideoContainerWidth = CleanNumber(GM_config.get("SubVideoContainerWidth"));
  226. var TrendingVideoContainerWidth = CleanNumber(GM_config.get('TrendingVideoContainerWidth'));
  227. var TrendingVideoContainerHeight = CleanNumber(GM_config.get('TrendingVideoContainerHeight'));
  228. var HQTN = GM_config.get('HQTN');
  229. var SearchVideoContainerWidth = CleanNumber(GM_config.get('SearchVideoContainerWidth'));
  230. var SearchVideoContainerHeight = CleanNumber(GM_config.get('SearchVideoContainerHeight'));
  231. var HideSearchVideoBadges = GM_config.get('HideSearchVideoBadges');
  232. var AutoExpandChannelVidContainers = GM_config.get('AutoExpandChannelVidContainers');
  233.  
  234.  
  235. GM_registerMenuCommand("Settings", () => {
  236. if(!GM_config.isOpen)
  237. GM_config.open();
  238. });
  239.  
  240. const ratioMultiplier = 16 / 9;
  241. var screenWidth = screen.width;
  242. if(!!document.getElementById("early-body")) { //if old youtube
  243. document.getElementById("content").setAttribute("style", "width: 99%;");
  244. } else { //new youtube
  245. //Main container width and padding
  246. if(true) {
  247. addGlobalStyle(`
  248. /*search*/
  249. ytd-search ytd-two-column-search-results-renderer.ytd-search,
  250. ytd-search ytd-two-column-search-results-renderer.ytd-search > #primary,
  251. /*home*/
  252. ytd-browse[page-subtype="home"] #contents.ytd-rich-grid-renderer,
  253. /*other*/
  254. ytd-browse > ytd-two-column-browse-results-renderer.ytd-browse
  255. {
  256. width: 100% !important;
  257. max-width: 100% !important;
  258. }
  259.  
  260. ytd-browse > ytd-two-column-browse-results-renderer.ytd-browse > #primary,
  261. ytd-search
  262. {
  263. padding: 16px;
  264. }
  265. `);
  266. }
  267.  
  268. //vertical lists to horizontal grid / video container sizing
  269. if(true) {
  270. //trending
  271. if(true) {
  272. addGlobalStyle(`
  273. /*container*/
  274. #grid-container.ytd-expanded-shelf-contents-renderer > .ytd-expanded-shelf-contents-renderer
  275. {
  276. display: inline-block;
  277. width: `+TrendingVideoContainerWidth+`px;
  278. height: `+TrendingVideoContainerHeight+`px;
  279. }
  280. #grid-container.ytd-expanded-shelf-contents-renderer > .ytd-expanded-shelf-contents-renderer > #dismissable
  281. {
  282. width: 100%;
  283. height: 100%;
  284. }
  285.  
  286. /*thumnail container*/
  287. #grid-container.ytd-expanded-shelf-contents-renderer > ytd-video-renderer:not([use-prominent-thumbs]) ytd-thumbnail.ytd-video-renderer,
  288. #grid-container.ytd-expanded-shelf-contents-renderer > ytd-video-renderer:not([use-prominent-thumbs]) ytd-thumbnail #thumbnail.ytd-thumbnail yt-img-shadow.ytd-thumbnail
  289. {
  290. height: 100%;
  291. width: `+(TrendingVideoContainerHeight * ratioMultiplier)+`px;
  292. }
  293.  
  294. /*thumnail shadow and image*/
  295. #grid-container.ytd-expanded-shelf-contents-renderer > ytd-video-renderer:not([use-prominent-thumbs]) ytd-thumbnail #thumbnail.ytd-thumbnail yt-img-shadow.ytd-thumbnail > img
  296. {
  297. height: 100% !important;
  298. width: 100% !important;
  299. }
  300. `);
  301. }
  302.  
  303. //search
  304. if(true) {
  305. addGlobalStyle(`
  306. /*container*/
  307. ytd-search ytd-video-renderer, ytd-search ytd-channel-renderer, ytd-search ytd-radio-renderer, ytd-search ytd-playlist-renderer
  308. {
  309. display: inline-block;
  310. width: `+SearchVideoContainerWidth+`px;
  311. height: `+SearchVideoContainerHeight+`px;
  312. box-sizing: border-box;
  313. }
  314. ytd-search ytd-video-renderer > #dismissable
  315. {
  316. width: 100%;
  317. height: 100%;
  318. }
  319.  
  320. /*thumnail container*/
  321. ytd-search ytd-video-renderer[use-prominent-thumbs] ytd-thumbnail.ytd-video-renderer,
  322. ytd-search ytd-radio-renderer[use-prominent-thumbs] ytd-thumbnail.ytd-radio-renderer,
  323. ytd-search ytd-playlist-renderer[use-prominent-thumbs] ytd-playlist-thumbnail.ytd-playlist-renderer
  324. {
  325. max-width: none;
  326. min-width: none;
  327. height: 100%;
  328. width: `+(SearchVideoContainerHeight * ratioMultiplier)+`px;
  329. -ms-flex: none;
  330. -webkit-flex: none;
  331. flex: none;
  332. }
  333. ytd-search ytd-radio-renderer.ytd-item-section-renderer,
  334. ytd-search ytd-playlist-renderer.ytd-item-section-renderer
  335. {
  336. display: flex;
  337. }
  338.  
  339. /*thumnail shadow and image*/
  340. ytd-search ytd-thumbnail #thumbnail.ytd-thumbnail yt-img-shadow.ytd-thumbnail,
  341. ytd-search ytd-thumbnail #thumbnail.ytd-thumbnail yt-img-shadow.ytd-thumbnail > img
  342. {
  343. width: 100%;
  344. height: 100%;
  345. }
  346.  
  347. /*other*/
  348. ytd-search #description-text.ytd-video-renderer
  349. {
  350. margin-bottom: 2px;
  351. }
  352. ytd-search ytd-video-renderer > #dismissable #channel-info
  353. {
  354. padding: 2px 0 0 0;
  355. }
  356. ytd-search #description-text.ytd-video-renderer
  357. {
  358. max-height: none;
  359. }
  360. `+(HideSearchVideoBadges ? `ytd-search ytd-badge-supported-renderer { display: none; }` : ``)+`
  361.  
  362. /*channel thumnail container*/
  363. ytd-search #avatar.ytd-channel-renderer,
  364. ytd-search ytd-channel-renderer[use-prominent-thumbs] #avatar-section.ytd-channel-renderer .channel-link.ytd-channel-renderer,
  365. ytd-search ytd-channel-renderer[use-prominent-thumbs] #avatar-section.ytd-channel-renderer
  366. {
  367. width: min-content;
  368. width: -moz-min-content;
  369. flex: none;
  370. max-width: none;
  371. min-width: 0;
  372. }
  373.  
  374. ytd-search div.ytd-video-renderer[id="channel-info"] { padding: 3px 0 0 0 !important; }
  375.  
  376. yt-showing-results-for-renderer { display: block; }
  377. `);
  378. }
  379.  
  380. //home
  381. if(true) {
  382. if(HomeVideoContainerWidthEnabled) {
  383. addGlobalStyle(`
  384. /*container*/
  385. ytd-browse[page-subtype="home"] ytd-rich-item-renderer
  386. {
  387. width: `+HomeVideoContainerWidth+`px;
  388. }
  389. `);
  390. }
  391. if(HideChannelIconNextToVideosOnHomePage) {
  392. addGlobalStyle(`ytd-browse[page-subtype="home"] #avatar-link.ytd-rich-grid-media { display: none; }`);
  393. }
  394. }
  395.  
  396. //subs
  397. if(true) {
  398. addGlobalStyle(`
  399. /*container*/
  400. ytd-browse[page-subtype="subscriptions"] #items.ytd-grid-renderer > ytd-grid-video-renderer.ytd-grid-renderer
  401. {
  402. width: `+SubVideoContainerWidth+`px;
  403. }
  404.  
  405. /*thumnail container*/
  406. ytd-browse[page-subtype="subscriptions"] ytd-thumbnail.ytd-grid-video-renderer
  407. {
  408. width: `+SubVideoContainerWidth+`px;
  409. height: `+(SubVideoContainerWidth / ratioMultiplier)+`px;
  410. }
  411.  
  412. /*thumnail shadow and image*/
  413. ytd-browse[page-subtype="subscriptions"] ytd-thumbnail #thumbnail.ytd-thumbnail yt-img-shadow.ytd-thumbnail,
  414. ytd-browse[page-subtype="subscriptions"] ytd-thumbnail #thumbnail.ytd-thumbnail yt-img-shadow.ytd-thumbnail > img
  415. {
  416. width: 100%;
  417. height: 100%;
  418. }
  419.  
  420. /*List layout vid container*/
  421. ytd-browse[page-subtype="subscriptions"] #grid-container.ytd-expanded-shelf-contents-renderer > .ytd-expanded-shelf-contents-renderer
  422. { width: 100%; }
  423. ytd-browse[page-subtype="subscriptions"] #grid-container.ytd-expanded-shelf-contents-renderer > .ytd-expanded-shelf-contents-renderer div.text-wrapper
  424. { max-width: none; }
  425. `);
  426. }
  427.  
  428. //multiple
  429. if(true) {
  430. addGlobalStyle(`#dismissible.ytd-video-renderer { height: 100%; }`);
  431. }
  432. }
  433.  
  434. //video container padding/margin
  435. if(true) {
  436. //trending
  437. if(true) {
  438. addGlobalStyle(`
  439. #grid-container.ytd-expanded-shelf-contents-renderer > .ytd-expanded-shelf-contents-renderer
  440. {
  441. padding: 0 10px 0 0;
  442. }
  443. #grid-container.ytd-expanded-shelf-contents-renderer > .ytd-expanded-shelf-contents-renderer:not(:last-child)
  444. {
  445. margin: 0 0 10px 0;
  446. }
  447. `);
  448. }
  449.  
  450. //search
  451. if(true) {
  452. addGlobalStyle(`
  453. ytd-search ytd-video-renderer.ytd-item-section-renderer,
  454. ytd-search ytd-channel-renderer.ytd-item-section-renderer,
  455. ytd-search ytd-radio-renderer.ytd-item-section-renderer,
  456. ytd-search ytd-playlist-renderer.ytd-item-section-renderer,
  457. ytd-search #items.ytd-vertical-list-renderer > .ytd-vertical-list-renderer
  458. {
  459. padding: 0 10px 0 0;
  460. margin: 10px 0 0 0;
  461. }
  462. ytd-search ytd-shelf-renderer.ytd-item-section-renderer
  463. {
  464. margin: 10px 0 0 0;
  465. }
  466. `);
  467. }
  468.  
  469. //home
  470. if(true) {
  471. addGlobalStyle(`
  472. ytd-browse[page-subtype="home"] ytd-rich-item-renderer
  473. {
  474. margin: 0 5px 20px 5px;
  475. }
  476. ytd-browse[page-subtype="home"] ytd-rich-section-renderer
  477. {
  478. margin: 0;
  479. }
  480. `);
  481. }
  482.  
  483. //subs
  484. if(true) {
  485. addGlobalStyle(`
  486. ytd-browse[page-subtype="subscriptions"] #items.ytd-grid-renderer > ytd-grid-video-renderer.ytd-grid-renderer
  487. {
  488. margin: 0 5px 15px 0;
  489. }
  490. `);
  491. }
  492. }
  493.  
  494. //channel page horizontal list arrow visibility
  495. if(true) {
  496. addGlobalStyle(`
  497. yt-horizontal-list-renderer[at-start] #left-arrow.yt-horizontal-list-renderer .arrow.yt-horizontal-list-renderer,
  498. yt-horizontal-list-renderer[at-end] #right-arrow.yt-horizontal-list-renderer .arrow.yt-horizontal-list-renderer
  499. {
  500. display: block;
  501. opacity: 1;
  502. }
  503. `+(!!window.chrome ? `
  504. #left-arrow.yt-horizontal-list-renderer { left: 20px; }
  505. #right-arrow.yt-horizontal-list-renderer { right: 20px; }
  506. ` : `
  507. #left-arrow.yt-horizontal-list-renderer { left: 0px; }
  508. #right-arrow.yt-horizontal-list-renderer { right: 40px; }
  509. `)
  510. );
  511. }
  512.  
  513. if(HQTN) {
  514. addGlobalStyle(`
  515. img.yt-img-shadow:not([src*='?'])
  516. {
  517. object-fit: cover;
  518. }
  519. `);
  520. }
  521. if(FPPCompOn) {
  522. addGlobalStyle(`
  523. /*========== Fade++ Compatibility ==========*/
  524. ytd-app #page-manager > ytd-browse:not([page-subtype="playlist"]) {
  525. display: block;
  526. }
  527. ytd-app[guide-persistent-and-visible] #page-manager > ytd-browse:not([page-subtype="playlist"]) ytd-two-column-browse-results-renderer.ytd-browse
  528. {
  529. margin-left: 250px !important;
  530. }
  531. `);
  532. //console.log("Youtube Wide video container Fade++ compatibilty style added to DOM");
  533. }
  534. }
  535.  
  536. if(AutoExpandChannelVidContainers || HQTN)
  537. {
  538. var lastCheckedURL = window.location.href;
  539. URLChanged(); //for initial page load
  540.  
  541. //poll for url changes
  542. setInterval(function(){
  543. if(lastCheckedURL != window.location.href)
  544. {
  545. lastCheckedURL = window.location.href;
  546. URLChanged();
  547. }
  548. }, 200);
  549. var waitForArrows, waitForSubsThumbnails;
  550. }
  551. /*============================================================*/
  552.  
  553. function AutoExpandContainers()
  554. {
  555. clearInterval(waitForArrows);
  556.  
  557. //=== clear potential old containers ===//
  558. let expandedEls = document.getElementsByClassName("expanded-wwc");
  559. //console.log("expanded els found: " + expandedEls.length);
  560. let numRemoved = 0;
  561.  
  562. //seems to always remove exactly half of them only, for some reason. So I guess do this until all have been removed
  563. while(expandedEls.length > 0)
  564. {
  565. for(let x = 0; x < expandedEls.length; x++)
  566. {
  567. if(!!expandedEls[x])
  568. {
  569. expandedEls[x].classList.remove("expanded-wwc");
  570. //console.log(++numRemoved + " cleared");
  571. }
  572. }
  573. expandedEls = document.getElementsByClassName("expanded-wwc");
  574. }
  575. //=== old containers cleared ===//
  576.  
  577. //=== unmark container arrows marked as clicked ===//
  578. numRemoved = 0;
  579. let clickedArrows = document.getElementsByClassName("clicked");
  580. //console.log("clicked found: " + clickedArrows.length);
  581. while(clickedArrows.length > 0)
  582. {
  583. for(let x = 0; x < clickedArrows.length; x++)
  584. {
  585. if(!!clickedArrows[x])
  586. {
  587. clickedArrows[x].classList.remove("clicked");
  588. //console.log(++numRemoved + " cleared");
  589. }
  590. }
  591. clickedArrows = document.getElementsByClassName("clicked");
  592. }
  593. //=== all arrows unmarked ===//
  594. //console.log("-expandedclear-");
  595.  
  596. //check that we are on a page that can have containers
  597. if(lastCheckedURL.includes("/user/") || lastCheckedURL.includes("/channel/") || lastCheckedURL.includes("/c/"))
  598. {
  599. //poll for untouched containers
  600. waitForArrows = setInterval(function(){
  601. //console.log("-searching...-");
  602. let arrowsRight = document.querySelectorAll("yt-horizontal-list-renderer:not(.expanded-wwc) > #right-arrow > ytd-button-renderer.arrow");
  603. let arrowsLeft = document.querySelectorAll("yt-horizontal-list-renderer:not(.expanded-wwc) > #left-arrow > ytd-button-renderer.arrow");
  604. if(!!arrowsRight && arrowsRight.length > 0 && !!arrowsLeft && arrowsLeft.length > 0)
  605. {
  606. //console.log("-found "+arrowsRight.length+"-");
  607. //do the thing for found untouched containers and mark them
  608. for(let i = 0; i < arrowsRight.length; i++)
  609. {
  610. if(!!arrowsRight[i] && arrowsRight[i].offsetParent !== null && !!arrowsLeft[i] && arrowsLeft[i].offsetParent !== null)
  611. {
  612. arrowsRight[i].parentElement.parentElement.classList.add("expanded-wwc");
  613. arrowsRight[i].click();
  614. //console.log("simulated click on right arrow");
  615. arrowsRight[i].classList.add("clicked");
  616. arrowsLeft[i].click();
  617. //console.log("simulated click on left arrow");
  618. arrowsLeft[i].classList.add("clicked");
  619. }
  620. }
  621. }
  622. }, 250);
  623. }
  624. }
  625.  
  626. function SwapSubsVidThumbnailsHQ()
  627. {
  628. clearInterval(waitForSubsThumbnails);
  629. if(lastCheckedURL.includes("/subscriptions") || lastCheckedURL.includes("/trending"))
  630. {
  631. waitForSubsThumbnails = setInterval(function(){
  632. let nails = document.querySelectorAll("img.yt-img-shadow[src*='hqdefault.jpg?']");
  633. //console.log("found " + nails.length + " LQ nails");
  634. for(let i = 0; i < nails.length; i++)
  635. nails[i].src = nails[i].src.split("?")[0];
  636. }, 200);
  637. }
  638. }
  639.  
  640. function URLChanged()
  641. {
  642. if(AutoExpandChannelVidContainers)
  643. AutoExpandContainers();
  644.  
  645. if(HQTN)
  646. SwapSubsVidThumbnailsHQ();
  647. }
  648. function CleanCSSValue(val)
  649. {
  650. val = val.trim();
  651.  
  652. //if only numbers...
  653. if(/^\d+$/.test(val))
  654. val += "px"; //...add px
  655.  
  656. return val;
  657. }
  658. function CleanNumber(val)
  659. {
  660. val = parseFloat(val);
  661.  
  662. return val;
  663. }
  664.  
  665. function addGlobalStyle(css)
  666. {
  667. var head, style;
  668. head = document.getElementsByTagName('head')[0];
  669. if (!head) { return; }
  670. style = document.createElement('style');
  671. style.type = 'text/css';
  672. style.innerHTML = css;
  673. head.appendChild(style);
  674. }
  675.  
  676. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址