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-10 提交的版本,查看 最新版本

  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.4
  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: auto !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. 'VPRecommendedSectionWidth':
  192. {
  193. 'section': 'Video Page Recommended',
  194. 'label': 'Recommended section width',
  195. 'title': 'The width of the recommended section holding the video containers. [Theater mode only]',
  196. 'type': 'unsigned float',
  197. 'default': '426'
  198. },
  199. 'VPRecommendedVideoContainerHeight':
  200. {
  201. 'label': 'Video height',
  202. 'title': 'The height of the container. This directly affects thumnail size and how much space is left for the other info [Theater mode only]',
  203. 'type': 'unsigned float',
  204. 'default': '94'
  205. },
  206. 'VPRecommendedColumnCount':
  207. {
  208. 'label': 'Video column count',
  209. 'title': 'How many columns of videos to display. This directly affects the video container width of each video. e.g. 2 = 2 columns where video container width is 50% of the section width [Theater mode only]',
  210. 'type': 'unsigned float',
  211. 'default': '1'
  212. },
  213.  
  214. 'AutoExpandChannelVidContainers':
  215. {
  216. 'section': 'Channel pages',
  217. 'label': 'Auto-expand horizontal video lists',
  218. 'type': 'checkbox',
  219. 'default': false
  220. }
  221. },
  222. 'frame': frame,
  223. 'css': configCSS
  224. }
  225. );
  226.  
  227. var refreshAfterSave = false;
  228. GM_config.onOpen = function(doc, win, frame) {
  229. let saveBtn = frame.querySelector("#SEYConfig_saveBtn");
  230. let clone = saveBtn.cloneNode();
  231. clone.id = "SEYConfig_saveRefreshBtn";
  232. clone.textContent = "Save & Refresh";
  233. saveBtn.parentNode.insertBefore(clone, saveBtn);
  234. clone.onclick = function(){
  235. refreshAfterSave = true;
  236. saveBtn.click();
  237. };
  238. };
  239. GM_config.onSave = function(){
  240. if(refreshAfterSave)
  241. location.reload();
  242. };
  243.  
  244. var FPPCompOn = GM_config.get('FPPCompOn');
  245. var HomeVideoContainerWidthEnabled = GM_config.get('HomeVideoContainerWidthEnabled');
  246. var HomeVideoContainerWidth = CleanNumber(GM_config.get('HomeVideoContainerWidth'));
  247. var HideChannelIconNextToVideosOnHomePage = GM_config.get('HideChannelIconNextToVideosOnHomePage');
  248. var SubVideoContainerWidth = CleanNumber(GM_config.get("SubVideoContainerWidth"));
  249. var TrendingVideoContainerWidth = CleanNumber(GM_config.get('TrendingVideoContainerWidth'));
  250. var TrendingVideoContainerHeight = CleanNumber(GM_config.get('TrendingVideoContainerHeight'));
  251. var HQTN = GM_config.get('HQTN');
  252. var SearchVideoContainerWidth = CleanNumber(GM_config.get('SearchVideoContainerWidth'));
  253. var SearchVideoContainerHeight = CleanNumber(GM_config.get('SearchVideoContainerHeight'));
  254. var HideSearchVideoBadges = GM_config.get('HideSearchVideoBadges');
  255. var AutoExpandChannelVidContainers = GM_config.get('AutoExpandChannelVidContainers');
  256. var VPRecommendedSectionWidth = CleanNumber(GM_config.get('VPRecommendedSectionWidth'));
  257. var VPRecommendedVideoContainerHeight = CleanNumber(GM_config.get('VPRecommendedVideoContainerHeight'));
  258. var VPRecommendedColumnCount = CleanNumber(GM_config.get('VPRecommendedColumnCount'));
  259.  
  260.  
  261. GM_registerMenuCommand("Settings", () => {
  262. if(!GM_config.isOpen)
  263. GM_config.open();
  264. });
  265.  
  266. const ratioMultiplier = 16 / 9;
  267. var screenWidth = screen.width;
  268. if(!!document.getElementById("early-body")) { //if old youtube
  269. document.getElementById("content").setAttribute("style", "width: 99%;");
  270. } else { //new youtube
  271. //Main container width and padding
  272. if(true) {
  273. addGlobalStyle(`
  274. /*search*/
  275. ytd-search ytd-two-column-search-results-renderer.ytd-search,
  276. ytd-search ytd-two-column-search-results-renderer.ytd-search > #primary,
  277. /*home*/
  278. ytd-browse[page-subtype="home"] #contents.ytd-rich-grid-renderer,
  279. /*video*/
  280. #content [role="main"][theater-requested_] #columns,
  281. /*other*/
  282. ytd-browse > ytd-two-column-browse-results-renderer.ytd-browse
  283. {
  284. width: 100% !important;
  285. max-width: 100% !important;
  286. }
  287.  
  288. ytd-browse > ytd-two-column-browse-results-renderer.ytd-browse > #primary,
  289. ytd-search,
  290. #columns
  291. {
  292. padding: 16px;
  293. }
  294. `);
  295. }
  296.  
  297. //vertical lists to horizontal grid / video container sizing
  298. if(true) {
  299. //trending
  300. if(true) {
  301. addGlobalStyle(`
  302. /*container*/
  303. #grid-container.ytd-expanded-shelf-contents-renderer > .ytd-expanded-shelf-contents-renderer
  304. {
  305. display: inline-block;
  306. width: `+TrendingVideoContainerWidth+`px;
  307. height: `+TrendingVideoContainerHeight+`px;
  308. }
  309. #grid-container.ytd-expanded-shelf-contents-renderer > .ytd-expanded-shelf-contents-renderer > #dismissable
  310. {
  311. width: 100%;
  312. height: 100%;
  313. }
  314.  
  315. /*thumnail container*/
  316. #grid-container.ytd-expanded-shelf-contents-renderer > ytd-video-renderer:not([use-prominent-thumbs]) ytd-thumbnail.ytd-video-renderer,
  317. #grid-container.ytd-expanded-shelf-contents-renderer > ytd-video-renderer:not([use-prominent-thumbs]) ytd-thumbnail #thumbnail.ytd-thumbnail yt-img-shadow.ytd-thumbnail
  318. {
  319. height: 100%;
  320. width: `+(TrendingVideoContainerHeight * ratioMultiplier)+`px;
  321. }
  322.  
  323. /*thumnail shadow and image*/
  324. #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
  325. {
  326. height: 100% !important;
  327. width: 100% !important;
  328. }
  329. `);
  330. }
  331.  
  332. //search
  333. if(true) {
  334. addGlobalStyle(`
  335. /*container*/
  336. ytd-search ytd-video-renderer, ytd-search ytd-channel-renderer, ytd-search ytd-radio-renderer, ytd-search ytd-playlist-renderer
  337. {
  338. display: inline-block;
  339. width: `+SearchVideoContainerWidth+`px;
  340. height: `+SearchVideoContainerHeight+`px;
  341. box-sizing: border-box;
  342. }
  343. ytd-search ytd-video-renderer > #dismissable
  344. {
  345. width: 100%;
  346. height: 100%;
  347. }
  348.  
  349. /*thumnail container*/
  350. ytd-search ytd-video-renderer[use-prominent-thumbs] ytd-thumbnail.ytd-video-renderer,
  351. ytd-search ytd-radio-renderer[use-prominent-thumbs] ytd-thumbnail.ytd-radio-renderer,
  352. ytd-search ytd-playlist-renderer[use-prominent-thumbs] ytd-playlist-thumbnail.ytd-playlist-renderer
  353. {
  354. max-width: none;
  355. min-width: none;
  356. height: 100%;
  357. width: `+(SearchVideoContainerHeight * ratioMultiplier)+`px;
  358. -ms-flex: none;
  359. -webkit-flex: none;
  360. flex: none;
  361. }
  362. ytd-search ytd-radio-renderer.ytd-item-section-renderer,
  363. ytd-search ytd-playlist-renderer.ytd-item-section-renderer
  364. {
  365. display: flex;
  366. }
  367.  
  368. /*thumnail shadow and image*/
  369. ytd-search ytd-thumbnail #thumbnail.ytd-thumbnail yt-img-shadow.ytd-thumbnail,
  370. ytd-search ytd-thumbnail #thumbnail.ytd-thumbnail yt-img-shadow.ytd-thumbnail > img
  371. {
  372. width: 100%;
  373. height: 100%;
  374. }
  375.  
  376. /*other*/
  377. ytd-search #description-text.ytd-video-renderer
  378. {
  379. margin-bottom: 2px;
  380. }
  381. ytd-search ytd-video-renderer > #dismissable #channel-info
  382. {
  383. padding: 2px 0 0 0;
  384. }
  385. ytd-search #description-text.ytd-video-renderer
  386. {
  387. max-height: none;
  388. }
  389. `+(HideSearchVideoBadges ? `ytd-search ytd-badge-supported-renderer { display: none; }` : ``)+`
  390.  
  391. /*channel thumnail container*/
  392. ytd-search #avatar.ytd-channel-renderer,
  393. ytd-search ytd-channel-renderer[use-prominent-thumbs] #avatar-section.ytd-channel-renderer .channel-link.ytd-channel-renderer,
  394. ytd-search ytd-channel-renderer[use-prominent-thumbs] #avatar-section.ytd-channel-renderer
  395. {
  396. width: min-content;
  397. width: -moz-min-content;
  398. flex: none;
  399. max-width: none;
  400. min-width: 0;
  401. }
  402.  
  403. ytd-search div.ytd-video-renderer[id="channel-info"] { padding: 3px 0 0 0 !important; }
  404.  
  405. yt-showing-results-for-renderer { display: block; }
  406. `);
  407. }
  408.  
  409. //home
  410. if(true) {
  411. if(HomeVideoContainerWidthEnabled) {
  412. addGlobalStyle(`
  413. /*container*/
  414. ytd-browse[page-subtype="home"] ytd-rich-item-renderer
  415. {
  416. width: `+HomeVideoContainerWidth+`px;
  417. }
  418. `);
  419. }
  420. if(HideChannelIconNextToVideosOnHomePage) {
  421. addGlobalStyle(`ytd-browse[page-subtype="home"] #avatar-link.ytd-rich-grid-media { display: none; }`);
  422. }
  423. }
  424.  
  425. //subs
  426. if(true) {
  427. addGlobalStyle(`
  428. /*container*/
  429. ytd-browse[page-subtype="subscriptions"] #items.ytd-grid-renderer > ytd-grid-video-renderer.ytd-grid-renderer
  430. {
  431. width: `+SubVideoContainerWidth+`px;
  432. }
  433.  
  434. /*thumnail container*/
  435. ytd-browse[page-subtype="subscriptions"] ytd-thumbnail.ytd-grid-video-renderer
  436. {
  437. width: `+SubVideoContainerWidth+`px;
  438. height: `+(SubVideoContainerWidth / ratioMultiplier)+`px;
  439. }
  440.  
  441. /*thumnail shadow and image*/
  442. ytd-browse[page-subtype="subscriptions"] ytd-thumbnail #thumbnail.ytd-thumbnail yt-img-shadow.ytd-thumbnail,
  443. ytd-browse[page-subtype="subscriptions"] ytd-thumbnail #thumbnail.ytd-thumbnail yt-img-shadow.ytd-thumbnail > img
  444. {
  445. width: 100%;
  446. height: 100%;
  447. }
  448.  
  449. /*List layout vid container*/
  450. ytd-browse[page-subtype="subscriptions"] #grid-container.ytd-expanded-shelf-contents-renderer > .ytd-expanded-shelf-contents-renderer
  451. { width: 100%; }
  452. ytd-browse[page-subtype="subscriptions"] #grid-container.ytd-expanded-shelf-contents-renderer > .ytd-expanded-shelf-contents-renderer div.text-wrapper
  453. { max-width: none; }
  454. `);
  455. }
  456.  
  457. //video page
  458. if(true) {
  459. addGlobalStyle(`
  460. /*thumnail container*/
  461. #content [role="main"][theater-requested_] #columns #secondary #items > ytd-item-section-renderer > #contents > .ytd-item-section-renderer
  462. {
  463. display: inline-block;
  464. width: calc(`+(100 / VPRecommendedColumnCount)+`% - 5px);
  465. height: `+VPRecommendedVideoContainerHeight+`px;
  466. margin: 0;
  467. flex-grow: 1;
  468. box-sizing: border-box;
  469. }
  470.  
  471. #content [role="main"][theater-requested_] #columns #secondary #items > ytd-item-section-renderer > #contents > .ytd-item-section-renderer > #dismissible
  472. {
  473. width: 100%;
  474. height: 100%;
  475. }
  476.  
  477. /*thumnail container*/
  478. [role="main"][theater-requested_] .ytd-item-section-renderer ytd-thumbnail,
  479. [role="main"][theater-requested_] .ytd-item-section-renderer ytd-thumbnail yt-img-shadow.ytd-thumbnail
  480. {
  481. height: 100%;
  482. width: `+(VPRecommendedVideoContainerHeight * ratioMultiplier)+`px;
  483. }
  484.  
  485. /*thumnail shadow and image*/
  486. [role="main"][theater-requested_] .ytd-item-section-renderer ytd-thumbnail yt-img-shadow.ytd-thumbnail > img
  487. {
  488. width: 100%;
  489. height: 100%;
  490. }
  491. `);
  492. }
  493.  
  494. //multiple
  495. if(true) {
  496. addGlobalStyle(`#dismissible.ytd-video-renderer { height: 100%; }`);
  497. }
  498. }
  499.  
  500. //video container padding/margin
  501. if(true) {
  502. //trending
  503. if(true) {
  504. addGlobalStyle(`
  505. #grid-container.ytd-expanded-shelf-contents-renderer > .ytd-expanded-shelf-contents-renderer
  506. {
  507. padding: 0 10px 0 0;
  508. }
  509. #grid-container.ytd-expanded-shelf-contents-renderer > .ytd-expanded-shelf-contents-renderer:not(:last-child)
  510. {
  511. margin: 0 0 10px 0;
  512. }
  513. `);
  514. }
  515.  
  516. //search
  517. if(true) {
  518. addGlobalStyle(`
  519. ytd-search ytd-video-renderer.ytd-item-section-renderer,
  520. ytd-search ytd-channel-renderer.ytd-item-section-renderer,
  521. ytd-search ytd-radio-renderer.ytd-item-section-renderer,
  522. ytd-search ytd-playlist-renderer.ytd-item-section-renderer,
  523. ytd-search #items.ytd-vertical-list-renderer > .ytd-vertical-list-renderer
  524. {
  525. padding: 0 10px 0 0;
  526. margin: 10px 0 0 0;
  527. }
  528. ytd-search ytd-shelf-renderer.ytd-item-section-renderer
  529. {
  530. margin: 10px 0 0 0;
  531. }
  532. `);
  533. }
  534.  
  535. //home
  536. if(true) {
  537. addGlobalStyle(`
  538. ytd-browse[page-subtype="home"] ytd-rich-item-renderer
  539. {
  540. margin: 0 5px 20px 5px;
  541. }
  542. ytd-browse[page-subtype="home"] ytd-rich-section-renderer
  543. {
  544. margin: 0;
  545. }
  546. `);
  547. }
  548.  
  549. //subs
  550. if(true) {
  551. addGlobalStyle(`
  552. ytd-browse[page-subtype="subscriptions"] #items.ytd-grid-renderer > ytd-grid-video-renderer.ytd-grid-renderer
  553. {
  554. margin: 0 5px 15px 0;
  555. }
  556. `);
  557. }
  558.  
  559. //video page
  560. if(true) {
  561. addGlobalStyle(`
  562. #content [role="main"][theater-requested_] #columns > #secondary
  563. {
  564. width: `+VPRecommendedSectionWidth+`px;
  565. }
  566. #content [role="main"][theater-requested_] #columns > #secondary #items #contents {
  567. display: flex;
  568. flex-wrap: wrap;
  569. gap: 8px 1px;
  570. }
  571. `);
  572. }
  573. }
  574.  
  575. //channel page horizontal list arrow visibility
  576. if(true) {
  577. addGlobalStyle(`
  578. yt-horizontal-list-renderer[at-start] #left-arrow.yt-horizontal-list-renderer .arrow.yt-horizontal-list-renderer,
  579. yt-horizontal-list-renderer[at-end] #right-arrow.yt-horizontal-list-renderer .arrow.yt-horizontal-list-renderer
  580. {
  581. display: block;
  582. opacity: 1;
  583. }
  584. `+(!!window.chrome ? `
  585. #left-arrow.yt-horizontal-list-renderer { left: 20px; }
  586. #right-arrow.yt-horizontal-list-renderer { right: 20px; }
  587. ` : `
  588. #left-arrow.yt-horizontal-list-renderer { left: 0px; }
  589. #right-arrow.yt-horizontal-list-renderer { right: 40px; }
  590. `)
  591. );
  592. }
  593.  
  594. if(HQTN) {
  595. addGlobalStyle(`
  596. img.yt-img-shadow:not([src*='?'])
  597. {
  598. object-fit: cover;
  599. }
  600. `);
  601. }
  602. if(FPPCompOn) {
  603. addGlobalStyle(`
  604. /*========== Fade++ Compatibility ==========*/
  605. ytd-app #page-manager > ytd-browse:not([page-subtype="playlist"]) {
  606. display: block;
  607. }
  608. ytd-app[guide-persistent-and-visible] #page-manager > ytd-browse:not([page-subtype="playlist"]) ytd-two-column-browse-results-renderer.ytd-browse
  609. {
  610. margin-left: 250px !important;
  611. }
  612. `);
  613. //console.log("Youtube Wide video container Fade++ compatibilty style added to DOM");
  614. }
  615. }
  616.  
  617. if(AutoExpandChannelVidContainers || HQTN)
  618. {
  619. var lastCheckedURL = window.location.href;
  620. URLChanged(); //for initial page load
  621.  
  622. //poll for url changes
  623. setInterval(function(){
  624. if(lastCheckedURL != window.location.href)
  625. {
  626. lastCheckedURL = window.location.href;
  627. URLChanged();
  628. }
  629. }, 200);
  630. var waitForArrows, waitForSubsThumbnails;
  631. }
  632. /*============================================================*/
  633.  
  634. function AutoExpandContainers()
  635. {
  636. clearInterval(waitForArrows);
  637.  
  638. //=== clear potential old containers ===//
  639. let expandedEls = document.getElementsByClassName("expanded-wwc");
  640. //console.log("expanded els found: " + expandedEls.length);
  641. let numRemoved = 0;
  642.  
  643. //seems to always remove exactly half of them only, for some reason. So I guess do this until all have been removed
  644. while(expandedEls.length > 0)
  645. {
  646. for(let x = 0; x < expandedEls.length; x++)
  647. {
  648. if(!!expandedEls[x])
  649. {
  650. expandedEls[x].classList.remove("expanded-wwc");
  651. //console.log(++numRemoved + " cleared");
  652. }
  653. }
  654. expandedEls = document.getElementsByClassName("expanded-wwc");
  655. }
  656. //=== old containers cleared ===//
  657.  
  658. //=== unmark container arrows marked as clicked ===//
  659. numRemoved = 0;
  660. let clickedArrows = document.getElementsByClassName("clicked");
  661. //console.log("clicked found: " + clickedArrows.length);
  662. while(clickedArrows.length > 0)
  663. {
  664. for(let x = 0; x < clickedArrows.length; x++)
  665. {
  666. if(!!clickedArrows[x])
  667. {
  668. clickedArrows[x].classList.remove("clicked");
  669. //console.log(++numRemoved + " cleared");
  670. }
  671. }
  672. clickedArrows = document.getElementsByClassName("clicked");
  673. }
  674. //=== all arrows unmarked ===//
  675. //console.log("-expandedclear-");
  676.  
  677. //check that we are on a page that can have containers
  678. if(lastCheckedURL.includes("/user/") || lastCheckedURL.includes("/channel/") || lastCheckedURL.includes("/c/"))
  679. {
  680. //poll for untouched containers
  681. waitForArrows = setInterval(function(){
  682. //console.log("-searching...-");
  683. let arrowsRight = document.querySelectorAll("yt-horizontal-list-renderer:not(.expanded-wwc) > #right-arrow > ytd-button-renderer.arrow");
  684. let arrowsLeft = document.querySelectorAll("yt-horizontal-list-renderer:not(.expanded-wwc) > #left-arrow > ytd-button-renderer.arrow");
  685. if(!!arrowsRight && arrowsRight.length > 0 && !!arrowsLeft && arrowsLeft.length > 0)
  686. {
  687. //console.log("-found "+arrowsRight.length+"-");
  688. //do the thing for found untouched containers and mark them
  689. for(let i = 0; i < arrowsRight.length; i++)
  690. {
  691. if(!!arrowsRight[i] && arrowsRight[i].offsetParent !== null && !!arrowsLeft[i] && arrowsLeft[i].offsetParent !== null)
  692. {
  693. arrowsRight[i].parentElement.parentElement.classList.add("expanded-wwc");
  694. arrowsRight[i].click();
  695. //console.log("simulated click on right arrow");
  696. arrowsRight[i].classList.add("clicked");
  697. arrowsLeft[i].click();
  698. //console.log("simulated click on left arrow");
  699. arrowsLeft[i].classList.add("clicked");
  700. }
  701. }
  702. }
  703. }, 250);
  704. }
  705. }
  706.  
  707. function SwapSubsVidThumbnailsHQ()
  708. {
  709. clearInterval(waitForSubsThumbnails);
  710. if(lastCheckedURL.includes("/subscriptions") || lastCheckedURL.includes("/trending"))
  711. {
  712. waitForSubsThumbnails = setInterval(function(){
  713. let nails = document.querySelectorAll("img.yt-img-shadow[src*='hqdefault.jpg?']");
  714. //console.log("found " + nails.length + " LQ nails");
  715. for(let i = 0; i < nails.length; i++)
  716. nails[i].src = nails[i].src.split("?")[0];
  717. }, 200);
  718. }
  719. }
  720.  
  721. function URLChanged()
  722. {
  723. if(AutoExpandChannelVidContainers)
  724. AutoExpandContainers();
  725.  
  726. if(HQTN)
  727. SwapSubsVidThumbnailsHQ();
  728. }
  729. function CleanCSSValue(val)
  730. {
  731. val = val.trim();
  732.  
  733. //if only numbers...
  734. if(/^\d+$/.test(val))
  735. val += "px"; //...add px
  736.  
  737. return val;
  738. }
  739. function CleanNumber(val)
  740. {
  741. val = parseFloat(val);
  742.  
  743. return val;
  744. }
  745.  
  746. function addGlobalStyle(css)
  747. {
  748. var head, style;
  749. head = document.getElementsByTagName('head')[0];
  750. if (!head) { return; }
  751. style = document.createElement('style');
  752. style.type = 'text/css';
  753. style.innerHTML = css;
  754. head.appendChild(style);
  755. }
  756.  
  757. })();

QingJ © 2025

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