Greasy Fork is available in English.

Space-efficient Youtube

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

Установить этот скрипт?
Рекомендуемый автором скрипт

Вам также может понравится Youtube - Fix channel links in sidebar recommendations.

Установить этот скрипт
  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. // @match https://www.youtube.com/*
  10. // @version 2.4.8
  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. var gmc = new GM_config({
  99. 'id': 'SEYConfig', // The id used for this instance of GM_config
  100. 'title': 'Space-efficient Youtube Config',
  101. 'fields': // Fields object
  102. {
  103. 'FPPCompOn': // This is the id of the field
  104. {
  105. 'section': 'Fade++',
  106. 'label': 'Fade++ compatibility mode', // Appears next to field
  107. 'type': 'checkbox', // Makes this setting a text field
  108. 'default': false // Default value if user doesn't change it
  109. },
  110.  
  111. 'HomeVideoContainerWidthEnabled':
  112. {
  113. 'section': 'Home page',
  114. 'label': 'Video container size mod enabled',
  115. '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.',
  116. 'type': 'checkbox',
  117. 'default': false
  118. },
  119. 'HomeVideoContainerWidth':
  120. {
  121. 'label': 'Video container width',
  122. 'title': 'The width of the container which includes both the thumbnail and the title/other info',
  123. 'type': 'unsigned float',
  124. 'default': '360'
  125. },
  126. 'HideChannelIconNextToVideosOnHomePage':
  127. {
  128. 'label': 'Hide channel icon in video container',
  129. 'type': 'checkbox',
  130. 'default': false
  131. },
  132.  
  133. 'SubVideoContainerWidth':
  134. {
  135. 'section': 'Subscriptions page',
  136. 'label': 'Video container width',
  137. 'title': 'The width of the container which includes both the thumbnail and the title/other info',
  138. 'type': 'unsigned float',
  139. 'default': '210'
  140. },
  141.  
  142. 'TrendingVideoContainerWidth':
  143. {
  144. 'section': 'Trending page',
  145. 'label': 'Video container width',
  146. 'title': 'The width of the container which includes both the thumbnail and the title/other info',
  147. 'type': 'unsigned float',
  148. 'default': '600'
  149. },
  150. 'TrendingVideoContainerHeight':
  151. {
  152. 'label': 'Video container height',
  153. 'title': 'The height of the container. This directly affects thumnail size and how much space is left for the other info',
  154. 'type': 'unsigned float',
  155. 'default': '138'
  156. },
  157.  
  158. 'HQTN':
  159. {
  160. 'section': 'Subscriptions & Trending pages',
  161. 'label': 'Load high quality thumbnails',
  162. '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.',
  163. 'type': 'checkbox',
  164. 'default': false
  165. },
  166.  
  167. 'SearchVideoContainerWidth':
  168. {
  169. 'section': 'Search results page',
  170. 'label': 'Video container width',
  171. 'title': 'The width of the container which includes both the thumbnail and the title/other info',
  172. 'type': 'unsigned float',
  173. 'default': '600'
  174. },
  175. 'SearchVideoContainerHeight':
  176. {
  177. 'label': 'Video container height',
  178. 'title': 'The height of the container. This directly affects thumnail size and how much space is left for the other info',
  179. 'type': 'unsigned float',
  180. 'default': '150'
  181. },
  182. 'HideSearchVideoBadges':
  183. {
  184. 'label': 'Hide video badges',
  185. 'title': 'Hides the little badges like New/4K/CC etc. on the video containers leaving more space for the description',
  186. 'type': 'checkbox',
  187. 'default': true
  188. },
  189.  
  190. 'VPRecommendedSectionWidth':
  191. {
  192. 'section': 'Video Page Recommended',
  193. 'label': 'Recommended section width',
  194. 'title': 'The width of the recommended section holding the video containers. [Theater mode only]',
  195. 'type': 'unsigned float',
  196. 'default': '426'
  197. },
  198. 'VPRecommendedVideoContainerHeight':
  199. {
  200. 'label': 'Video height',
  201. 'title': 'The height of the container. This directly affects thumnail size and how much space is left for the other info [Theater mode only]',
  202. 'type': 'unsigned float',
  203. 'default': '94'
  204. },
  205. 'VPRecommendedColumnCount':
  206. {
  207. 'label': 'Video column count',
  208. '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]',
  209. 'type': 'unsigned float',
  210. 'default': '1'
  211. },
  212.  
  213. 'AutoExpandChannelVidContainers':
  214. {
  215. 'section': 'Channel pages',
  216. 'label': 'Auto-expand horizontal video lists',
  217. 'type': 'checkbox',
  218. 'default': false
  219. }
  220. },
  221. 'frame': frame,
  222. 'css': configCSS,
  223. 'events': {
  224. //called after GM_config init has finished
  225. 'init': function() { MainScriptWrapper(); }
  226. }
  227. });
  228.  
  229.  
  230. function MainScriptWrapper()
  231. {
  232. var refreshAfterSave = false;
  233. gmc.onOpen = function(doc, win, frame) {
  234. let saveBtn = frame.querySelector("#SEYConfig_saveBtn");
  235. let clone = saveBtn.cloneNode();
  236. clone.id = "SEYConfig_saveRefreshBtn";
  237. clone.textContent = "Save & Refresh";
  238. saveBtn.parentNode.insertBefore(clone, saveBtn);
  239. clone.onclick = function(){
  240. refreshAfterSave = true;
  241. saveBtn.click();
  242. };
  243. };
  244. gmc.onSave = function(){
  245. if(refreshAfterSave)
  246. location.reload();
  247. };
  248.  
  249. var FPPCompOn = gmc.get('FPPCompOn');
  250. var HomeVideoContainerWidthEnabled = gmc.get('HomeVideoContainerWidthEnabled');
  251. var HomeVideoContainerWidth = CleanNumber(gmc.get('HomeVideoContainerWidth'));
  252. var HideChannelIconNextToVideosOnHomePage = gmc.get('HideChannelIconNextToVideosOnHomePage');
  253. var SubVideoContainerWidth = CleanNumber(gmc.get("SubVideoContainerWidth"));
  254. var TrendingVideoContainerWidth = CleanNumber(gmc.get('TrendingVideoContainerWidth'));
  255. var TrendingVideoContainerHeight = CleanNumber(gmc.get('TrendingVideoContainerHeight'));
  256. var HQTN = gmc.get('HQTN');
  257. var SearchVideoContainerWidth = CleanNumber(gmc.get('SearchVideoContainerWidth'));
  258. var SearchVideoContainerHeight = CleanNumber(gmc.get('SearchVideoContainerHeight'));
  259. var HideSearchVideoBadges = gmc.get('HideSearchVideoBadges');
  260. var AutoExpandChannelVidContainers = gmc.get('AutoExpandChannelVidContainers');
  261. var VPRecommendedSectionWidth = CleanNumber(gmc.get('VPRecommendedSectionWidth'));
  262. var VPRecommendedVideoContainerHeight = CleanNumber(gmc.get('VPRecommendedVideoContainerHeight'));
  263. var VPRecommendedColumnCount = CleanNumber(gmc.get('VPRecommendedColumnCount'));
  264.  
  265.  
  266. GM_registerMenuCommand("Settings", () => {
  267. if(!gmc.isOpen)
  268. gmc.open();
  269. });
  270.  
  271. const ratioMultiplier = 16 / 9;
  272. var screenWidth = screen.width;
  273. if(!!document.getElementById("early-body")) { //if old youtube
  274. document.getElementById("content").setAttribute("style", "width: 99%;");
  275. } else { //new youtube
  276. //Main container width and padding
  277. if(true) {
  278. addGlobalStyle(`
  279. /*search*/
  280. ytd-search ytd-two-column-search-results-renderer.ytd-search,
  281. ytd-search ytd-two-column-search-results-renderer.ytd-search #primary,
  282. /*home*/
  283. ytd-browse[page-subtype="home"] #contents.ytd-rich-grid-renderer,
  284. /*video*/
  285. #content [role="main"][theater-requested_] #columns,
  286. /*other*/
  287. ytd-browse > ytd-two-column-browse-results-renderer.ytd-browse
  288. {
  289. width: 100% !important;
  290. max-width: 100% !important;
  291. }
  292.  
  293. ytd-browse > ytd-two-column-browse-results-renderer.ytd-browse > #primary,
  294. ytd-search,
  295. #columns
  296. {
  297. padding: 0 16px;
  298. }
  299.  
  300. #content [role="main"][theater-requested_] #columns {
  301. box-sizing: border-box;
  302. }
  303.  
  304. ytd-watch-flexy:not([theater]):not([fullscreen]):not([no-top-margin]) #primary.ytd-watch-flexy, ytd-watch-flexy:not([theater]):not([fullscreen]):not([no-top-margin]) #secondary.ytd-watch-flexy
  305. {
  306. padding-top: 5px;
  307. }
  308.  
  309. /*Community page*/
  310. ytd-browse[page-subtype="channels"] #contents.ytd-section-list-renderer
  311. {
  312. margin: 0 auto;
  313. }
  314. `);
  315. }
  316.  
  317. //page-manager element tends to sometimes be a few pixels too large for some reason...
  318. //...so hiding overflow
  319. if(true) {
  320. addGlobalStyle(`
  321. ytd-page-manager#page-manager { overflow: hidden; }
  322. `);
  323. }
  324.  
  325. //vertical lists to horizontal grid / video container sizing
  326. if(true) {
  327. //trending
  328. if(true) {
  329. addGlobalStyle(`
  330. /*container*/
  331. #grid-container.ytd-expanded-shelf-contents-renderer > .ytd-expanded-shelf-contents-renderer
  332. {
  333. display: inline-block;
  334. width: `+TrendingVideoContainerWidth+`px;
  335. height: `+TrendingVideoContainerHeight+`px;
  336. }
  337. #grid-container.ytd-expanded-shelf-contents-renderer > .ytd-expanded-shelf-contents-renderer > #dismissable
  338. {
  339. width: 100%;
  340. height: 100%;
  341. }
  342.  
  343. /*thumnail container*/
  344. #grid-container.ytd-expanded-shelf-contents-renderer > ytd-video-renderer:not([use-prominent-thumbs]) ytd-thumbnail.ytd-video-renderer,
  345. #grid-container.ytd-expanded-shelf-contents-renderer > ytd-video-renderer:not([use-prominent-thumbs]) ytd-thumbnail #thumbnail.ytd-thumbnail yt-img-shadow.ytd-thumbnail
  346. {
  347. height: 100%;
  348. width: `+(TrendingVideoContainerHeight * ratioMultiplier)+`px;
  349. }
  350.  
  351. /*thumnail shadow and image*/
  352. #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
  353. {
  354. height: 100% !important;
  355. width: 100% !important;
  356. }
  357. `);
  358. }
  359.  
  360. //search
  361. if(true) {
  362. addGlobalStyle(`
  363. /*container*/
  364. ytd-search ytd-video-renderer, ytd-search ytd-channel-renderer, ytd-search ytd-radio-renderer, ytd-search ytd-playlist-renderer
  365. {
  366. display: inline-block;
  367. width: `+SearchVideoContainerWidth+`px;
  368. height: `+SearchVideoContainerHeight+`px;
  369. box-sizing: border-box;
  370. }
  371. ytd-search ytd-video-renderer > #dismissable
  372. {
  373. width: 100%;
  374. height: 100%;
  375. }
  376.  
  377. /*thumnail container*/
  378. ytd-search ytd-video-renderer[use-prominent-thumbs] ytd-thumbnail.ytd-video-renderer,
  379. ytd-search ytd-radio-renderer[use-prominent-thumbs] ytd-thumbnail.ytd-radio-renderer,
  380. ytd-search ytd-playlist-renderer[use-prominent-thumbs] ytd-playlist-thumbnail.ytd-playlist-renderer
  381. {
  382. max-width: none;
  383. min-width: none;
  384. height: 100%;
  385. width: `+(SearchVideoContainerHeight * ratioMultiplier)+`px;
  386. -ms-flex: none;
  387. -webkit-flex: none;
  388. flex: none;
  389. }
  390. ytd-search ytd-radio-renderer.ytd-item-section-renderer,
  391. ytd-search ytd-playlist-renderer.ytd-item-section-renderer
  392. {
  393. display: flex;
  394. }
  395.  
  396. /*thumnail shadow and image*/
  397. ytd-search ytd-thumbnail #thumbnail.ytd-thumbnail yt-img-shadow.ytd-thumbnail,
  398. ytd-search ytd-thumbnail #thumbnail.ytd-thumbnail yt-img-shadow.ytd-thumbnail > img
  399. {
  400. width: 100%;
  401. height: 100%;
  402. }
  403.  
  404. /*other*/
  405. ytd-search #description-text.ytd-video-renderer
  406. {
  407. margin-bottom: 2px;
  408. }
  409. ytd-search ytd-video-renderer > #dismissable #channel-info
  410. {
  411. padding: 2px 0 0 0;
  412. }
  413. ytd-search #description-text.ytd-video-renderer
  414. {
  415. max-height: none;
  416. }
  417. `+(HideSearchVideoBadges ? `ytd-search ytd-badge-supported-renderer { display: none; }` : ``)+`
  418.  
  419. /*channel thumnail container*/
  420. ytd-search #avatar.ytd-channel-renderer,
  421. ytd-search ytd-channel-renderer[use-prominent-thumbs] #avatar-section.ytd-channel-renderer .channel-link.ytd-channel-renderer,
  422. ytd-search ytd-channel-renderer[use-prominent-thumbs] #avatar-section.ytd-channel-renderer
  423. {
  424. width: min-content;
  425. width: -moz-min-content;
  426. flex: none;
  427. max-width: none;
  428. min-width: 0;
  429. }
  430.  
  431. ytd-search div.ytd-video-renderer[id="channel-info"] { padding: 3px 0 0 0 !important; }
  432.  
  433. yt-showing-results-for-renderer { display: block; }
  434. `);
  435. }
  436.  
  437. //home
  438. if(true) {
  439. if(HomeVideoContainerWidthEnabled) {
  440. addGlobalStyle(`
  441. /*container*/
  442. ytd-browse[page-subtype="home"] ytd-rich-item-renderer
  443. {
  444. width: `+HomeVideoContainerWidth+`px;
  445. }
  446. `);
  447. }
  448. if(HideChannelIconNextToVideosOnHomePage) {
  449. addGlobalStyle(`ytd-browse[page-subtype="home"] #avatar-link.ytd-rich-grid-media { display: none; }`);
  450. }
  451. }
  452.  
  453. //subs
  454. if(true) {
  455. addGlobalStyle(`
  456. /*container*/
  457. ytd-browse[page-subtype="subscriptions"] #items.ytd-grid-renderer > ytd-grid-video-renderer.ytd-grid-renderer
  458. {
  459. width: `+SubVideoContainerWidth+`px;
  460. }
  461.  
  462. /*thumnail container*/
  463. ytd-browse[page-subtype="subscriptions"] ytd-thumbnail.ytd-grid-video-renderer
  464. {
  465. width: `+SubVideoContainerWidth+`px;
  466. height: `+(SubVideoContainerWidth / ratioMultiplier)+`px;
  467. }
  468.  
  469. /*thumnail shadow and image*/
  470. ytd-browse[page-subtype="subscriptions"] ytd-thumbnail #thumbnail.ytd-thumbnail yt-img-shadow.ytd-thumbnail,
  471. ytd-browse[page-subtype="subscriptions"] ytd-thumbnail #thumbnail.ytd-thumbnail yt-img-shadow.ytd-thumbnail > img
  472. {
  473. width: 100%;
  474. height: 100%;
  475. }
  476.  
  477. /*List layout vid container*/
  478. ytd-browse[page-subtype="subscriptions"] #grid-container.ytd-expanded-shelf-contents-renderer > .ytd-expanded-shelf-contents-renderer
  479. { width: 100%; }
  480. ytd-browse[page-subtype="subscriptions"] #grid-container.ytd-expanded-shelf-contents-renderer > .ytd-expanded-shelf-contents-renderer div.text-wrapper
  481. { max-width: none; }
  482. `);
  483. }
  484.  
  485. //video page
  486. if(true) {
  487. addGlobalStyle(`
  488. /*thumnail container*/
  489. #content [role="main"][theater-requested_] #columns #secondary #items > ytd-item-section-renderer > #contents > .ytd-item-section-renderer
  490. {
  491. display: inline-block;
  492. width: calc(`+(100 / VPRecommendedColumnCount)+`% - 5px);
  493. height: `+VPRecommendedVideoContainerHeight+`px;
  494. margin: 0;
  495. flex-grow: 1;
  496. box-sizing: border-box;
  497. }
  498.  
  499. #content [role="main"][theater-requested_] #columns #secondary #items > ytd-item-section-renderer > #contents > .ytd-item-section-renderer > #dismissible
  500. {
  501. width: 100%;
  502. height: 100%;
  503. }
  504.  
  505. /*thumnail container*/
  506. [role="main"][theater-requested_] .ytd-item-section-renderer ytd-thumbnail,
  507. [role="main"][theater-requested_] .ytd-item-section-renderer ytd-thumbnail yt-img-shadow.ytd-thumbnail
  508. {
  509. height: 100%;
  510. width: `+(VPRecommendedVideoContainerHeight * ratioMultiplier)+`px;
  511. }
  512.  
  513. /*thumnail shadow and image*/
  514. [role="main"][theater-requested_] .ytd-item-section-renderer ytd-thumbnail yt-img-shadow.ytd-thumbnail > img
  515. {
  516. width: 100%;
  517. height: 100%;
  518. }
  519. `);
  520. }
  521.  
  522. //Community page
  523. if(false) {
  524. addGlobalStyle(`
  525. ytd-browse[page-subtype="channels"] #contents.ytd-section-list-renderer > .ytd-backstage-items
  526. {
  527. max-width: unset;
  528. width: 852px;
  529. }
  530. `);
  531. }
  532.  
  533. //multiple
  534. if(true) {
  535. addGlobalStyle(`#dismissible.ytd-video-renderer { height: 100%; }`);
  536. }
  537. }
  538.  
  539. //video container padding/margin
  540. if(true) {
  541. //chapter select
  542. if(true) {
  543. addGlobalStyle(`
  544. #expandable-metadata.ytd-video-renderer:not(:empty) {
  545. margin: 0;
  546. z-index: 999;
  547. }
  548. `);
  549. }
  550.  
  551. //trending
  552. if(true) {
  553. addGlobalStyle(`
  554. #grid-container.ytd-expanded-shelf-contents-renderer > .ytd-expanded-shelf-contents-renderer
  555. {
  556. padding: 0 10px 0 0;
  557. }
  558. #grid-container.ytd-expanded-shelf-contents-renderer > .ytd-expanded-shelf-contents-renderer:not(:last-child)
  559. {
  560. margin: 0 0 10px 0;
  561. }
  562. `);
  563. }
  564.  
  565. //search
  566. if(true) {
  567. addGlobalStyle(`
  568. ytd-search ytd-video-renderer.ytd-item-section-renderer,
  569. ytd-search ytd-channel-renderer.ytd-item-section-renderer,
  570. ytd-search ytd-radio-renderer.ytd-item-section-renderer,
  571. ytd-search ytd-playlist-renderer.ytd-item-section-renderer,
  572. ytd-search #items.ytd-vertical-list-renderer > .ytd-vertical-list-renderer
  573. {
  574. padding: 0 10px 0 0;
  575. margin: 10px 0 0 0;
  576. }
  577. ytd-search ytd-shelf-renderer.ytd-item-section-renderer
  578. {
  579. margin: 10px 0 0 0;
  580. }
  581. `);
  582. }
  583.  
  584. //home
  585. if(true) {
  586. addGlobalStyle(`
  587. ytd-browse[page-subtype="home"] ytd-rich-item-renderer
  588. {
  589. margin: 0 5px 20px 5px;
  590. }
  591. ytd-browse[page-subtype="home"] ytd-rich-section-renderer
  592. {
  593. margin: 0;
  594. }
  595. `);
  596. }
  597.  
  598. //subs
  599. if(true) {
  600. addGlobalStyle(`
  601. ytd-browse[page-subtype="subscriptions"] #items.ytd-grid-renderer > ytd-grid-video-renderer.ytd-grid-renderer
  602. {
  603. margin: 0 5px 15px 0;
  604. }
  605. `);
  606. }
  607.  
  608. //video page
  609. if(true) {
  610. addGlobalStyle(`
  611. #content [role="main"][theater-requested_] #columns > #secondary
  612. {
  613. width: `+VPRecommendedSectionWidth+`px;
  614. }
  615. #content [role="main"][theater-requested_] #columns > #secondary #items #contents {
  616. display: flex;
  617. flex-wrap: wrap;
  618. gap: 8px 1px;
  619. }
  620. `);
  621. }
  622. }
  623.  
  624. //channel page horizontal list arrow visibility
  625. if(true) {
  626. addGlobalStyle(`
  627. yt-horizontal-list-renderer[at-start] #left-arrow.yt-horizontal-list-renderer .arrow.yt-horizontal-list-renderer,
  628. yt-horizontal-list-renderer[at-end] #right-arrow.yt-horizontal-list-renderer .arrow.yt-horizontal-list-renderer
  629. {
  630. display: block;
  631. opacity: 1;
  632. }
  633. `+(!!window.chrome ? `
  634. #left-arrow.yt-horizontal-list-renderer { left: 20px; }
  635. #right-arrow.yt-horizontal-list-renderer { right: 20px; }
  636. ` : `
  637. #left-arrow.yt-horizontal-list-renderer { left: 0px; }
  638. #right-arrow.yt-horizontal-list-renderer { right: 40px; }
  639. `)
  640. );
  641. }
  642.  
  643. if(HQTN) {
  644. addGlobalStyle(`
  645. img.yt-img-shadow:not([src*='?'])
  646. {
  647. object-fit: cover;
  648. }
  649. `);
  650. }
  651. if(FPPCompOn) {
  652. addGlobalStyle(`
  653. /*========== Fade++ Compatibility ==========*/
  654. ytd-app #page-manager > ytd-browse:not([page-subtype="playlist"]) {
  655. display: block;
  656. }
  657. ytd-app[guide-persistent-and-visible] #page-manager > ytd-browse:not([page-subtype="playlist"]) ytd-two-column-browse-results-renderer.ytd-browse
  658. {
  659. margin-left: 250px !important;
  660. }
  661. `);
  662. //console.log("Youtube Wide video container Fade++ compatibilty style added to DOM");
  663. }
  664. }
  665.  
  666. if(AutoExpandChannelVidContainers || HQTN)
  667. {
  668. var lastCheckedURL = window.location.href;
  669. URLChanged(); //for initial page load
  670.  
  671. //poll for url changes
  672. setInterval(function(){
  673. if(lastCheckedURL != window.location.href)
  674. {
  675. lastCheckedURL = window.location.href;
  676. URLChanged();
  677. }
  678. }, 200);
  679. var waitForArrows, waitForSubsThumbnails;
  680. }
  681.  
  682. //Remove limits on items per row on home page (by moving items outside the rows and removing the rows themselves)
  683. if(HomeVideoContainerWidthEnabled)
  684. {
  685. setInterval(MoveAllVideoItemsOutsideRowsAndRemoveRowsOnHomePage, 100);
  686. }
  687.  
  688. /*============================================================*/
  689.  
  690. function MoveAllVideoItemsOutsideRowsAndRemoveRowsOnHomePage()
  691. {
  692. //Get all rows
  693. let rows = document.querySelectorAll("ytd-browse[page-subtype='home'] ytd-rich-grid-renderer > #contents ytd-rich-grid-row.ytd-rich-grid-renderer");
  694. for(let i = 0; i < rows.length; i++)
  695. {
  696. //get the first item in current row, until none can be found
  697. let curItem;
  698. while((curItem = rows[i].querySelector("ytd-rich-item-renderer.ytd-rich-grid-row")))
  699. {
  700. //move the item outside the row
  701. rows[i].parentNode.insertBefore(curItem, rows[i]);
  702. }
  703. rows[i].remove();
  704. }
  705. }
  706.  
  707. function AutoExpandContainers()
  708. {
  709. clearInterval(waitForArrows);
  710.  
  711. //=== clear potential old containers ===//
  712. let expandedEls = document.getElementsByClassName("expanded-wwc");
  713. //console.log("expanded els found: " + expandedEls.length);
  714. let numRemoved = 0;
  715.  
  716. //seems to always remove exactly half of them only, for some reason. So I guess do this until all have been removed
  717. while(expandedEls.length > 0)
  718. {
  719. for(let x = 0; x < expandedEls.length; x++)
  720. {
  721. if(!!expandedEls[x])
  722. {
  723. expandedEls[x].classList.remove("expanded-wwc");
  724. //console.log(++numRemoved + " cleared");
  725. }
  726. }
  727. expandedEls = document.getElementsByClassName("expanded-wwc");
  728. }
  729. //=== old containers cleared ===//
  730.  
  731. //=== unmark container arrows marked as clicked ===//
  732. numRemoved = 0;
  733. let clickedArrows = document.getElementsByClassName("clicked");
  734. //console.log("clicked found: " + clickedArrows.length);
  735. while(clickedArrows.length > 0)
  736. {
  737. for(let x = 0; x < clickedArrows.length; x++)
  738. {
  739. if(!!clickedArrows[x])
  740. {
  741. clickedArrows[x].classList.remove("clicked");
  742. //console.log(++numRemoved + " cleared");
  743. }
  744. }
  745. clickedArrows = document.getElementsByClassName("clicked");
  746. }
  747. //=== all arrows unmarked ===//
  748. //console.log("-expandedclear-");
  749.  
  750. //check that we are on a page that can have containers
  751. if(lastCheckedURL.includes("/user/") || lastCheckedURL.includes("/channel/") || lastCheckedURL.includes("/c/"))
  752. {
  753. //poll for untouched containers
  754. waitForArrows = setInterval(function(){
  755. //console.log("-searching...-");
  756. let arrowsRight = document.querySelectorAll("yt-horizontal-list-renderer:not(.expanded-wwc) > #right-arrow > ytd-button-renderer.arrow");
  757. let arrowsLeft = document.querySelectorAll("yt-horizontal-list-renderer:not(.expanded-wwc) > #left-arrow > ytd-button-renderer.arrow");
  758. if(!!arrowsRight && arrowsRight.length > 0 && !!arrowsLeft && arrowsLeft.length > 0)
  759. {
  760. //console.log("-found "+arrowsRight.length+"-");
  761. //do the thing for found untouched containers and mark them
  762. for(let i = 0; i < arrowsRight.length; i++)
  763. {
  764. if(!!arrowsRight[i] && arrowsRight[i].offsetParent !== null && !!arrowsLeft[i] && arrowsLeft[i].offsetParent !== null)
  765. {
  766. arrowsRight[i].parentElement.parentElement.classList.add("expanded-wwc");
  767. arrowsRight[i].click();
  768. //console.log("simulated click on right arrow");
  769. arrowsRight[i].classList.add("clicked");
  770. arrowsLeft[i].click();
  771. //console.log("simulated click on left arrow");
  772. arrowsLeft[i].classList.add("clicked");
  773. }
  774. }
  775. }
  776. }, 250);
  777. }
  778. }
  779. }
  780.  
  781.  
  782.  
  783.  
  784.  
  785.  
  786. function SwapSubsVidThumbnailsHQ()
  787. {
  788. clearInterval(waitForSubsThumbnails);
  789. if(lastCheckedURL.includes("/subscriptions") || lastCheckedURL.includes("/trending"))
  790. {
  791. waitForSubsThumbnails = setInterval(function(){
  792. let nails = document.querySelectorAll("img.yt-img-shadow[src*='hqdefault.jpg?']");
  793. //console.log("found " + nails.length + " LQ nails");
  794. for(let i = 0; i < nails.length; i++)
  795. nails[i].src = nails[i].src.split("?")[0];
  796. }, 200);
  797. }
  798. }
  799.  
  800. function URLChanged()
  801. {
  802. if(AutoExpandChannelVidContainers)
  803. AutoExpandContainers();
  804.  
  805. if(HQTN)
  806. SwapSubsVidThumbnailsHQ();
  807. }
  808. function CleanCSSValue(val)
  809. {
  810. val = val.trim();
  811.  
  812. //if only numbers...
  813. if(/^\d+$/.test(val))
  814. val += "px"; //...add px
  815.  
  816. return val;
  817. }
  818. function CleanNumber(val)
  819. {
  820. val = parseFloat(val);
  821.  
  822. return val;
  823. }
  824.  
  825. function addGlobalStyle(css)
  826. {
  827. var head, style;
  828. head = document.getElementsByTagName('head')[0];
  829. if (!head) { return; }
  830. style = document.createElement('style');
  831. style.type = 'text/css';
  832. style.innerHTML = css;
  833. head.appendChild(style);
  834. }
  835.  
  836. })();