Greasy Fork is available in English.

youtube auto-hide header

youtubeのヘッダーを自動で隠します(スクロールか画面上部ホバーで表示)

  1. // ==UserScript==
  2. // @name youtube auto-hide header
  3. // @namespace http://tampermonkey.net/
  4. // @version 2.2
  5. // @description youtubeのヘッダーを自動で隠します(スクロールか画面上部ホバーで表示)
  6. // @author y_kahou
  7. // @match https://www.youtube.com/*
  8. // @grant GM_setValue
  9. // @grant GM_getValue
  10. // @grant GM_registerMenuCommand
  11. // @license MIT
  12. // @require https://greatest.deepsurf.us/scripts/419955-y-method/code/y_method.js?version=1051149
  13. // @noframes
  14. // ==/UserScript==
  15.  
  16.  
  17. /** スクロール後ヘッダーが表示されている時間 */
  18. const SHOW_INTERVAL_SCROLL = 3000;
  19.  
  20. /** topにマウスを載せてからヘッダーが出るまでの時間 */
  21. const SHOW_INTERVAL_HOVER = 300;
  22.  
  23. /** topからマウスをどけてヘッダーが消えるまでの時間 */
  24. const HIDE_INTERVAL_HOVER = 1000;
  25.  
  26. let mouseX = -1, mouseY = -1;
  27.  
  28. (function() {
  29.  
  30. // innerHTML を使うためのおまじない
  31. if (window.trustedTypes && trustedTypes.createPolicy) {
  32. if (!trustedTypes.defaultPolicy) {
  33. const passThroughFn = (x) => x;
  34. trustedTypes.createPolicy('default', {
  35. createHTML: passThroughFn,
  36. createScriptURL: passThroughFn,
  37. createScript: passThroughFn,
  38. });
  39. }
  40. }
  41.  
  42. // ページ遷移を検知できるようにする
  43. y_method.DetectPagetransition();
  44.  
  45. y_method.PageLauncher([
  46. {
  47. match: 'https://www.youtube.com/watch',
  48. css: `html:not([fullscreen]) ytd-app { margin-top: -56px; }`,
  49. run: hide
  50. }
  51. ]);
  52. // 最初の一回
  53. y_method.TriggerPagetransition();
  54.  
  55.  
  56. y_method.addStyle('auto-hide-header', `
  57. #masthead #background {
  58. opacity: 1!important;
  59. }
  60. #yah-setting {
  61. position: absolute;
  62. top: 0px;
  63. left: 0px;
  64. width: 100%;
  65. height: 100%;
  66. background: #888b;
  67. z-index: 10000;
  68. user-select: none;
  69. }
  70. #yah-setting .modal-back {
  71. position: absolute;
  72. width: 100%;
  73. height: 100%;
  74. z-index: -1;
  75. }
  76. #yah-setting .modal {
  77. display: grid;
  78. justify-items: center;
  79. margin: 100px auto;
  80. padding: 50px;
  81. width: fit-content;
  82. background: white;
  83. }
  84. #yah-setting label {
  85. font-size: large;
  86. }
  87. `);
  88.  
  89. const defaultValue = (key, val) =>
  90. (typeof GM_getValue(key) == "undefined") ? GM_setValue(key, val) : '';
  91. defaultValue('yah-1', true);
  92. defaultValue('yah-2', false);
  93.  
  94. // setting
  95. GM_registerMenuCommand('Setting', () => {
  96. let modal = document.createElement('div')
  97. modal.id = 'yah-setting'
  98. modal.innerHTML = trustedTypes.defaultPolicy.createHTML(`
  99. <div id="yah-setting">
  100. <div class="modal-back"></div>
  101. <div class="modal">
  102. <h1>show action</h1>
  103. <label><input type="checkbox" id="yah-1">scroll</label>
  104. <label><input type="checkbox" id="yah-2">hover top</label>
  105. </div>
  106. </div>`)
  107. document.body.appendChild(modal)
  108.  
  109. function col(id) {
  110. const chk = document.querySelector('#' + id);
  111. chk.checked = GM_getValue(id);
  112. chk.addEventListener('change', e => GM_setValue(id, e.currentTarget.checked));
  113. }
  114. col('yah-1');
  115. col('yah-2');
  116. document.querySelector('#yah-setting .modal-back').addEventListener('click', e => {
  117. modal.parentNode.removeChild(modal)
  118. })
  119. })
  120.  
  121.  
  122. function show() {
  123. document.querySelector('ytd-app').removeAttribute('masthead-hidden')
  124. }
  125. function hide() {
  126. let act = document.activeElement
  127. if (act.tagName == 'INPUT' && act.id == 'search') return;
  128. if (0 <= mouseY && mouseY <= 56) return;
  129. document.querySelector('ytd-app').setAttribute('masthead-hidden','')
  130. }
  131.  
  132. // scroll
  133. let interval;
  134. window.onscroll = () => {
  135. if (!GM_getValue('yah-1')) return;
  136. show();
  137. clearTimeout(interval);
  138. interval = setTimeout(hide, SHOW_INTERVAL_SCROLL);
  139. }
  140.  
  141.  
  142. let hover;
  143. document.addEventListener('mousemove', e => {
  144. if (!GM_getValue('yah-2')) return;
  145. mouseX = e.clientX;
  146. mouseY = e.clientY;
  147.  
  148. if (0 <= mouseY && mouseY <= 56) {
  149. if (!hover) {
  150. hover = true;
  151. document.dispatchEvent(new Event('headhover'))
  152. }
  153. } else {
  154. if (hover) {
  155. hover = false;
  156. document.dispatchEvent(new Event('headleave'))
  157. }
  158. }
  159. })
  160. document.addEventListener('mouseleave', e => {
  161. if (!GM_getValue('yah-2')) return;
  162. if (hover) {
  163. hover = false;
  164. mouseY = -1;
  165. document.dispatchEvent(new Event('headleave'))
  166. }
  167. })
  168.  
  169. let over, leave;
  170. document.addEventListener('headhover', () => {
  171. if (!GM_getValue('yah-2')) return;
  172. clearTimeout(over);
  173. clearTimeout(leave);
  174. over = setTimeout(show, SHOW_INTERVAL_HOVER);
  175. })
  176. document.addEventListener('headleave', () => {
  177. if (!GM_getValue('yah-2')) return;
  178. clearTimeout(over);
  179. clearTimeout(leave);
  180. leave = setTimeout(hide, HIDE_INTERVAL_HOVER);
  181. })
  182.  
  183.  
  184. // // blur
  185. // $(document).on('blur', 'input#search', e => {
  186. // e.currentTarget.blur();
  187. // hide();
  188. // });
  189.  
  190.  
  191. // fullscreen
  192. document.addEventListener('fullscreenchange', e => {
  193. if (document.fullscreenElement) {
  194. document.querySelector('html').setAttribute('fullscreen', '')
  195. } else {
  196. document.querySelector('html').removeAttribute('fullscreen')
  197. }
  198. })
  199. })();