Youtube Middle Click Search (Updated)

Middle clicking the YouTube search or suggestions opens results in a new tab

  1. // ==UserScript==
  2. // @name Youtube Middle Click Search (Updated)
  3. // @namespace https://greasyfork.org/users/649
  4. // @version 3.0
  5. // @description Middle clicking the YouTube search or suggestions opens results in a new tab
  6. // @author flowscript
  7. // @match *://www.youtube.com/*
  8. // @grant GM_openInTab
  9. // @license MIT
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. const SEL_SEARCH_BTN = '.ytSearchboxComponentSearchButton';
  16. const SEL_SUGGESTION = '.ytSuggestionComponentSuggestion';
  17. const SEL_CLEAR_BTN = '.ytSearchboxComponentClearButton';
  18. const SEL_INPUT = 'input.ytSearchboxComponentInput';
  19.  
  20. // Convert user’s query into something like "foo+bar"
  21. function encodeURIWithPlus(str) {
  22. return encodeURIComponent(str).replace(/%20/g, '+');
  23. }
  24.  
  25. function isSearchButton(el) {
  26. return el.closest?.(SEL_SEARCH_BTN);
  27. }
  28.  
  29. function getSuggestionEl(el) {
  30. return el.closest?.(SEL_SUGGESTION);
  31. }
  32.  
  33. function isClearButton(el) {
  34. return el.closest?.(SEL_CLEAR_BTN);
  35. }
  36.  
  37. function getSearchInputValue() {
  38. const input = document.querySelector(SEL_INPUT);
  39. return input?.value.trim() || '';
  40. }
  41.  
  42. function getSuggestionText(suggestionEl) {
  43. const textEl = suggestionEl.querySelector('.ytSuggestionComponentLeftContainer span');
  44. return textEl?.textContent.trim() || '';
  45. }
  46.  
  47. // Open query in new tab
  48. function openInNewTab(query) {
  49. if (!query) return;
  50. const url = `${location.origin}/results?search_query=${encodeURIWithPlus(query)}`;
  51. GM_openInTab(url, true);
  52. }
  53.  
  54. // Open query in current tab
  55. function openInSameTab(query) {
  56. if (!query) return;
  57. const url = `${location.origin}/results?search_query=${encodeURIWithPlus(query)}`;
  58. window.location.href = url;
  59. }
  60.  
  61. /**
  62. * 1) Intercept mousedown on button=1 (middle-click),
  63. * open results in new tab immediately, then block normal click.
  64. */
  65. document.addEventListener(
  66. 'mousedown',
  67. (e) => {
  68. if (e.button !== 1) return; // only middle-click
  69. const target = e.target;
  70.  
  71. // If it’s the main search button
  72. if (isSearchButton(target)) {
  73. e.preventDefault();
  74. e.stopPropagation();
  75. e.stopImmediatePropagation();
  76. openInNewTab(getSearchInputValue());
  77. return;
  78. }
  79.  
  80. // If it’s a suggestion
  81. const suggestionEl = getSuggestionEl(target);
  82. if (suggestionEl && !isClearButton(target)) {
  83. e.preventDefault();
  84. e.stopPropagation();
  85. e.stopImmediatePropagation();
  86. openInNewTab(getSuggestionText(suggestionEl));
  87. }
  88. },
  89. true
  90. );
  91.  
  92. /**
  93. * 2) Intercept normal left-click (button=0),
  94. * open results in same tab, block YouTube’s single-page script.
  95. */
  96. document.addEventListener(
  97. 'click',
  98. (e) => {
  99. if (e.button !== 0) return; // only left-click
  100. const target = e.target;
  101.  
  102. // If it’s the main search button
  103. if (isSearchButton(target)) {
  104. e.preventDefault();
  105. e.stopPropagation();
  106. e.stopImmediatePropagation();
  107. openInSameTab(getSearchInputValue());
  108. return;
  109. }
  110.  
  111. // If it’s a suggestion
  112. const suggestionEl = getSuggestionEl(target);
  113. if (suggestionEl && !isClearButton(target)) {
  114. e.preventDefault();
  115. e.stopPropagation();
  116. e.stopImmediatePropagation();
  117. openInSameTab(getSuggestionText(suggestionEl));
  118. }
  119. },
  120. true
  121. );
  122. })();