Force Bing Dark Mode

Automatically selects dark mode in Bing settings

  1. // ==UserScript==
  2. // @name Force Bing Dark Mode
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.0
  5. // @description Automatically selects dark mode in Bing settings
  6. // @author Henry Suen
  7. // @match *://*.bing.com/*
  8. // @grant none
  9. // @license MIT
  10. // @run-at document-idle
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. // Save the dark mode preference in cookies and localStorage
  17. function saveDarkModePreference() {
  18. // Set cookie with dark mode preference (expires in 365 days)
  19. document.cookie = "_UR=QS=0&TQS=0&ThemeID=dark; path=/; domain=.bing.com; max-age=" + 60*60*24*365;
  20.  
  21. // Also save to localStorage
  22. if (localStorage) {
  23. localStorage.setItem('_UR', '{"TQS":"0","QS":"0","ThemeID":"dark"}');
  24. }
  25. }
  26.  
  27. // Click the dark mode radio button if it exists and isn't already selected
  28. function selectDarkMode() {
  29. // Find the dark mode radio button by its specific ID
  30. const darkRadio = document.querySelector('#rdiodark');
  31.  
  32. if (darkRadio && !darkRadio.checked) {
  33. console.log('Bing Force Dark Mode: Found dark mode option, clicking it');
  34. darkRadio.click();
  35. return true;
  36. }
  37.  
  38. // Alternative selector using the value and name attributes
  39. const darkRadioAlt = document.querySelector('input[type="radio"][name="da_rdio"][value="1"]');
  40.  
  41. if (darkRadioAlt && !darkRadioAlt.checked) {
  42. console.log('Bing Force Dark Mode: Found dark mode option (alt method), clicking it');
  43. darkRadioAlt.click();
  44. return true;
  45. }
  46.  
  47. return false;
  48. }
  49.  
  50. // Attempt to find the appearance section and expand it if needed
  51. function findAndExpandAppearanceSection() {
  52. // Look for the appearance section by its class and content
  53. const appearanceSection = document.querySelector('div[class*="hb_section hb_top_sec hb_expanded"][aria-controls="hbradiobtn"]');
  54.  
  55. if (!appearanceSection) {
  56. // If not expanded, find the appearance dropdown
  57. const appearanceDropdown = document.querySelector('div.hb_title_col:contains("Appearance")') ||
  58. document.querySelector('div:contains("Appearance")').closest('.hb_titlerow');
  59.  
  60. if (appearanceDropdown) {
  61. const expandButton = appearanceDropdown.closest('[aria-expanded="false"]');
  62. if (expandButton) {
  63. console.log('Bing Force Dark Mode: Expanding appearance section');
  64. expandButton.click();
  65. return true;
  66. }
  67. }
  68. } else {
  69. // Appearance section is already expanded
  70. return true;
  71. }
  72.  
  73. return false;
  74. }
  75.  
  76. // Main function to force dark mode
  77. function forceDarkMode() {
  78. // First save the preference
  79. saveDarkModePreference();
  80.  
  81. // Try direct selection
  82. if (selectDarkMode()) {
  83. console.log('Bing Force Dark Mode: Successfully applied dark mode');
  84. return;
  85. }
  86.  
  87. // If we couldn't find the dark mode option directly, try to open the appearance section
  88. if (findAndExpandAppearanceSection()) {
  89. // Wait for the section to expand
  90. setTimeout(() => {
  91. if (selectDarkMode()) {
  92. console.log('Bing Force Dark Mode: Successfully applied dark mode after expanding section');
  93. }
  94. }, 300);
  95. }
  96. }
  97.  
  98. // Settings menu may load dynamically, so we'll set up a MutationObserver
  99. const observer = new MutationObserver((mutations) => {
  100. for (const mutation of mutations) {
  101. if (mutation.addedNodes && mutation.addedNodes.length > 0) {
  102. // Look for settings dropdown being added to the DOM
  103. const settingsElements = document.querySelectorAll('div[class*="hb_section hb_top_sec"]');
  104. if (settingsElements.length > 0) {
  105. forceDarkMode();
  106. // Once we've found and processed the settings, we can disconnect the observer
  107. observer.disconnect();
  108. break;
  109. }
  110. }
  111. }
  112. });
  113.  
  114. // Start observing for the settings panel
  115. observer.observe(document.body, { childList: true, subtree: true });
  116.  
  117. // Also run after the page has loaded
  118. window.addEventListener('load', () => {
  119. setTimeout(forceDarkMode, 1000);
  120. });
  121.  
  122. // Run immediately too in case the page is already loaded
  123. saveDarkModePreference();
  124. setTimeout(forceDarkMode, 500);
  125. })();