Reddit Search Tab on Google

Adds a Reddit tab on Google search pages with various settings options for site and keyword search.

  1. // ==UserScript==
  2. // @name Reddit Search Tab on Google
  3. // @version 1.0
  4. // @description Adds a Reddit tab on Google search pages with various settings options for site and keyword search.
  5. // @namespace https://github.com/JrdnRgrs/reddit-search-tab-on-google
  6. // @author Jordan Rogers
  7. // @match *://*.google.com/search*
  8. // @icon https://www.redditstatic.com/desktop2x/img/favicon/favicon-32x32.png
  9. // @run-at document-end
  10. // @grant GM_setValue
  11. // @grant GM_getValue
  12. // @license MIT
  13. // ==/UserScript==
  14.  
  15. (function() {
  16. 'use strict';
  17.  
  18. // Settings: Change these to configure the script behavior
  19. const tabOnly = false; // Set to true if you want only the tab that adds "site:reddit.com"
  20. const tabDropdown = true; // Set to true if you want the settings displayed as a basic dropdown when the Reddit tab is clicked
  21. const caretDropdown = false; // Set to true if you want the settings displayed when the caret is clicked
  22. const iconDropdown = false; // Set to true if you want the settings displayed when the settings icon is clicked
  23.  
  24. function addRedditTab() {
  25. const searchTabsContainer = document.querySelectorAll('[role="list"]');
  26.  
  27. if (searchTabsContainer.length > 0) {
  28. const searchTabs = searchTabsContainer[0];
  29.  
  30. // Create the Reddit tab container
  31. const redditTabContainer = document.createElement('div');
  32. redditTabContainer.setAttribute('role', 'listitem');
  33. redditTabContainer.style.position = 'relative';
  34. redditTabContainer.style.display = 'flex';
  35. redditTabContainer.style.alignItems = 'center';
  36.  
  37. // Create Reddit button
  38. const redditButton = document.createElement('a');
  39. redditButton.href = '#';
  40. redditButton.className = 'nPDzT T3FoJb';
  41. redditButton.role = 'link';
  42. redditButton.innerHTML = `
  43. <div class="YmvwI">
  44. <img src="https://www.redditstatic.com/desktop2x/img/favicon/favicon-32x32.png" alt="Reddit" style="height:16px;margin-right:5px;">
  45. Reddit
  46. </div>
  47. `;
  48. redditTabContainer.appendChild(redditButton);
  49.  
  50. if (tabOnly) {
  51. // Add click event to the Reddit button to perform the search with "site:reddit.com"
  52. redditButton.addEventListener('click', function(e) {
  53. e.preventDefault();
  54. const currentUrl = new URL(window.location.href);
  55. const queryParams = currentUrl.searchParams;
  56. const currentQuery = queryParams.get('q');
  57.  
  58. if (!currentQuery.includes('site:reddit.com')) {
  59. queryParams.set('q', `${currentQuery} site:reddit.com`);
  60. }
  61. currentUrl.search = queryParams.toString();
  62. window.location.href = currentUrl.toString();
  63. });
  64. }
  65.  
  66. if (tabDropdown) {
  67. // Create the dropdown container
  68. const redditDropdown = document.createElement('div');
  69. redditDropdown.className = 'SF7xd';
  70. redditDropdown.setAttribute('role', 'listitem');
  71. redditDropdown.innerHTML = `
  72. <g-popup jsname="V68bde" class="CzKhHb" jscontroller="DPreE" jsaction="A05xBd:IYtByb;EOZ57e:WFrRFb;">
  73. <div jsname="oYxtQd" class="CcNe6e" aria-expanded="false" aria-haspopup="true" role="button" tabindex="0" jsaction="WFrRFb;keydown:uYT2Vb" style="display: inline-flex; align-items: center; padding: 0 10px; cursor: pointer;">
  74. <div class="Lu57id" style="display: inline-flex; align-items: center;">
  75. <span style="height:16px;line-height:16px;width:16px;margin-right:5px;" class="z1asCe SaPW2b">
  76. <img src="https://www.redditstatic.com/desktop2x/img/favicon/favicon-32x32.png" alt="Reddit" style="height:16px;">
  77. </span>
  78. Reddit
  79. </div>
  80. </div>
  81. <div jsname="V68bde" class="UjBGL iRQHZe" style="z-index: 200; display: none; position: absolute; top: 35px;">
  82. <div jsname="xl07Ob" class="CybWFf" tabindex="-1">
  83. <div class="LtmTod">
  84. <div role="listitem" data-hveid="CD8QAA">
  85. <a href="#" class="LatpMc d4DFfb nPDzT T3FoJb" role="link">
  86. <div class="eJWNqc YmvwI" jsname="bVqjv">Site</div>
  87. </a>
  88. </div>
  89. </div>
  90. <div class="LtmTod">
  91. <div role="listitem" data-hveid="CEEQAA">
  92. <a href="#" class="LatpMc d4DFfb nPDzT T3FoJb" role="link">
  93. <div class="eJWNqc YmvwI" jsname="bVqjv">Keyword</div>
  94. </a>
  95. </div>
  96. </div>
  97. </div>
  98. </div>
  99. </g-popup>
  100. `;
  101.  
  102. // Add event listeners for the dropdown toggle
  103. const dropdownButton = redditDropdown.querySelector('[aria-haspopup="true"]');
  104. const dropdownMenu = redditDropdown.querySelector('.UjBGL');
  105.  
  106. dropdownButton.addEventListener('click', function() {
  107. const isExpanded = dropdownButton.getAttribute('aria-expanded') === 'true';
  108. dropdownButton.setAttribute('aria-expanded', !isExpanded);
  109. dropdownMenu.style.display = !isExpanded ? 'block' : 'none';
  110. });
  111.  
  112. // Add event listeners for the dropdown items
  113. const siteLink = redditDropdown.querySelector('.LtmTod:first-child a');
  114. const keywordLink = redditDropdown.querySelector('.LtmTod:last-child a');
  115.  
  116. siteLink.addEventListener('click', function(e) {
  117. e.preventDefault();
  118. const currentUrl = new URL(window.location.href);
  119. const queryParams = currentUrl.searchParams;
  120. const currentQuery = queryParams.get('q');
  121.  
  122. if (!currentQuery.includes('site:reddit.com')) {
  123. queryParams.set('q', `${currentQuery} site:reddit.com`);
  124. currentUrl.search = queryParams.toString();
  125. window.location.href = currentUrl.toString();
  126. }
  127. });
  128.  
  129. keywordLink.addEventListener('click', function(e) {
  130. e.preventDefault();
  131. const currentUrl = new URL(window.location.href);
  132. const queryParams = currentUrl.searchParams;
  133. const currentQuery = queryParams.get('q');
  134.  
  135. if (!currentQuery.includes('reddit')) {
  136. queryParams.set('q', `${currentQuery} reddit`);
  137. currentUrl.search = queryParams.toString();
  138. window.location.href = currentUrl.toString();
  139. }
  140. });
  141.  
  142. // Append the Reddit dropdown to the search tabs container
  143. searchTabs.appendChild(redditDropdown);
  144. }
  145.  
  146. if (caretDropdown) {
  147. // Create caret icon
  148. const caretIcon = document.createElement('span');
  149. caretIcon.textContent = '▼';
  150. caretIcon.style.marginLeft = '5px';
  151. caretIcon.style.cursor = 'pointer';
  152. redditTabContainer.appendChild(caretIcon);
  153.  
  154. // Create dropdown for the caret
  155. const settingsDropdown = document.createElement('div');
  156. settingsDropdown.style.position = 'absolute';
  157. settingsDropdown.style.backgroundColor = 'var(--gZl0ff, #303134)';
  158. settingsDropdown.style.color = '#e8eaed';
  159. settingsDropdown.style.border = '1px solid var(--p9J9c, #5f6368)';
  160. settingsDropdown.style.padding = '5px 10px';
  161. settingsDropdown.style.display = 'none';
  162. settingsDropdown.style.zIndex = '300';
  163. settingsDropdown.style.top = '100%';
  164. settingsDropdown.style.left = '0';
  165. settingsDropdown.innerHTML = `
  166. <label>
  167. <input type="radio" name="reddit-search-mode" value="site" ${GM_getValue('searchMode', 'site') === 'site' ? 'checked' : ''}>
  168. Use site:reddit.com
  169. </label><br>
  170. <label>
  171. <input type="radio" name="reddit-search-mode" value="keyword" ${GM_getValue('searchMode', 'site') === 'keyword' ? 'checked' : ''}>
  172. Use keyword "reddit"
  173. </label>
  174. `;
  175. redditTabContainer.appendChild(settingsDropdown);
  176.  
  177. // Toggle dropdown on caret icon click
  178. caretIcon.addEventListener('click', function(e) {
  179. e.stopPropagation();
  180. e.preventDefault();
  181. settingsDropdown.style.display = settingsDropdown.style.display === 'none' ? 'block' : 'none';
  182. });
  183.  
  184. // Save selected option and update the Reddit tab click behavior
  185. settingsDropdown.querySelectorAll('input[name="reddit-search-mode"]').forEach(radio => {
  186. radio.addEventListener('change', function() {
  187. GM_setValue('searchMode', this.value);
  188. settingsDropdown.style.display = 'none';
  189. });
  190. });
  191.  
  192. // Close dropdown if clicking outside
  193. document.addEventListener('click', function(e) {
  194. if (!redditTabContainer.contains(e.target)) {
  195. settingsDropdown.style.display = 'none';
  196. }
  197. });
  198. }
  199.  
  200. if (iconDropdown) {
  201. // Add settings icon next to the Reddit tab
  202. const settingsButton = document.createElement('span');
  203. settingsButton.innerHTML = '⚙️';
  204. settingsButton.style.cursor = 'pointer';
  205. settingsButton.style.marginLeft = '10px';
  206. redditTabContainer.appendChild(settingsButton);
  207.  
  208. // Create settings popup
  209. const settingsPopup = document.createElement('div');
  210. settingsPopup.style.position = 'absolute';
  211. settingsPopup.style.backgroundColor = 'var(--gZl0ff, #303134)';
  212. settingsPopup.style.color = '#e8eaed';
  213. settingsPopup.style.border = '1px solid var(--p9J9c, #5f6368)';
  214. settingsPopup.style.padding = '10px';
  215. settingsPopup.style.display = 'none';
  216. settingsPopup.style.zIndex = '300';
  217. settingsPopup.innerHTML = `
  218. <label>
  219. <input type="radio" name="reddit-search-mode" value="site" ${GM_getValue('searchMode', 'site') === 'site' ? 'checked' : ''}>
  220. Use site:reddit.com
  221. </label><br>
  222. <label>
  223. <input type="radio" name="reddit-search-mode" value="keyword" ${GM_getValue('searchMode', 'site') === 'keyword' ? 'checked' : ''}>
  224. Use keyword "reddit"
  225. </label>
  226. `;
  227.  
  228. // Toggle settings popup on icon click
  229. settingsButton.addEventListener('click', function() {
  230. settingsPopup.style.display = settingsPopup.style.display === 'none' ? 'block' : 'none';
  231. });
  232.  
  233. // Save selected option and update the Reddit tab click behavior
  234. settingsPopup.querySelectorAll('input[name="reddit-search-mode"]').forEach(radio => {
  235. radio.addEventListener('change', function() {
  236. GM_setValue('searchMode', this.value);
  237. settingsPopup.style.display = 'none';
  238. });
  239. });
  240.  
  241. // Position the popup correctly
  242. settingsButton.addEventListener('click', function() {
  243. const rect = settingsButton.getBoundingClientRect();
  244. settingsPopup.style.left = `${rect.left}px`;
  245. settingsPopup.style.top = `${rect.bottom + window.scrollY}px`;
  246. });
  247.  
  248. // Append settings popup to body
  249. document.body.appendChild(settingsPopup);
  250. }
  251. if (tabOnly || caretDropdown || iconDropdown) {
  252.  
  253. // Add click event to the Reddit tab to perform the search based on the selected mode
  254. redditButton.addEventListener('click', function(e) {
  255. e.preventDefault();
  256. const searchMode = GM_getValue('searchMode', 'site');
  257. const currentUrl = new URL(window.location.href);
  258. const queryParams = currentUrl.searchParams;
  259. const currentQuery = queryParams.get('q');
  260.  
  261. if (searchMode === 'site') {
  262. if (!currentQuery.includes('site:reddit.com')) {
  263. queryParams.set('q', `${currentQuery} site:reddit.com`);
  264. }
  265. } else {
  266. if (!currentQuery.includes('reddit')) {
  267. queryParams.set('q', `${currentQuery} reddit`);
  268. }
  269. }
  270. currentUrl.search = queryParams.toString();
  271. window.location.href = currentUrl.toString();
  272. });
  273.  
  274. searchTabs.appendChild(redditTabContainer);
  275. }
  276. }
  277. }
  278.  
  279. // Run the function to add the Reddit tab
  280. addRedditTab();
  281. })();