Wordle Warn on Already Used Letters

When you type a letter that is confirmed absent in Wordle, this script will highlight it in red as a warning. Hopefully will help prevent dumb mistakes.

  1. // ==UserScript==
  2. // @name Wordle Warn on Already Used Letters
  3. // @namespace http://tampermonkey.net/
  4. // @version 2024-02-07
  5. // @description When you type a letter that is confirmed absent in Wordle, this script will highlight it in red as a warning. Hopefully will help prevent dumb mistakes.
  6. // @author Glench
  7. // @match https://www.nytimes.com/games/wordle/index.html
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=nytimes.com
  9. // @grant none
  10. // @license MIT
  11. // ==/UserScript==
  12. (function() {
  13. 'use strict';
  14. function on_DOM_change(selector, cb) {
  15. // Select the node that will be observed for mutations
  16. const targetNode = document.body;
  17. // Options for the observer (which mutations to observe)
  18. const config = { attributes: true, childList: true, subtree: true };
  19. // Callback function to execute when mutations are observed
  20. const callback = function(mutationsList, observer) {
  21. for(const mutation of mutationsList) {
  22. var newNodes = mutation.addedNodes;
  23. if (newNodes.length == 0) {
  24. if (mutation.target.matches(selector)) {
  25. return cb(mutation.target)
  26. }
  27. }
  28. var match = Array.from(newNodes).find(el => (el.matches && el.matches(selector)))
  29. if (!match) {
  30. Array.from(newNodes).forEach(el => {
  31. var children = el.querySelectorAll && el.querySelectorAll(selector)
  32. if (children) {
  33. children.forEach(cb)
  34. }
  35. })
  36. } else {
  37. cb(mutation.target)
  38. }
  39. }
  40. };
  41. // Create an observer instance linked to the callback function
  42. const observer = new MutationObserver(callback);
  43. // Start observing the target node for configured mutations
  44. observer.observe(targetNode, config);
  45. Array.from(document.querySelectorAll(selector)).forEach(cb);
  46. }
  47. on_DOM_change('div[data-state="tbd"]', function(el) {
  48. const disallowed_letters = Array.from(document.querySelectorAll('div[data-state="absent"]')).map(x => x.innerText)
  49. const confirmed_letters = Array.from(document.querySelectorAll('div[data-state="correct"]')).map(x => x.innerText)
  50. const misplaced_letters = Array.from(document.querySelectorAll('div[data-state="present"]')).map(x => x.innerText)
  51.  
  52. const letter = el.innerText;
  53.  
  54. if (disallowed_letters.includes(letter) && !confirmed_letters.includes(letter) && !misplaced_letters.includes(letter)) {
  55. el.style.color = 'red';
  56. } else {
  57. el.style.removeProperty('color');
  58. }
  59. })
  60.  
  61. // make sure when answer is submitted that the red warning is removed
  62. on_DOM_change('div[data-state="correct"], div[data-state="absent"], div[data-state="present"]', function(el) {
  63. el.removeAttribute('style');
  64. })
  65.  
  66. })();