WhatsApp Right-Click Dropdown Menu

Opens the options menu of a message on right-click in WhatsApp Web, replacing normal right click behavior.

  1. // ==UserScript==
  2. // @name WhatsApp Right-Click Dropdown Menu
  3. // @namespace https://web.whatsapp.com/
  4. // @version 1.1
  5. // @license CC BY-NC-SA 4.0
  6. // @description Opens the options menu of a message on right-click in WhatsApp Web, replacing normal right click behavior.
  7. // @author Dan
  8. // @match *://web.whatsapp.com/*
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. function attachContextMenuHandler(node) {
  16. if (node.classList && (node.classList.contains('message-out') || node.classList.contains('message-in'))) {
  17. node.addEventListener('contextmenu', function(event) {
  18. // If the target is a link, image, or selected text, allow the default context menu
  19. const target = event.target;
  20. if (target.nodeName === 'A' || target.nodeName === 'IMG' || window.getSelection().toString().length > 0) {
  21. return; // Don't prevent default behavior
  22. }
  23.  
  24. event.preventDefault();
  25.  
  26. // Try to find the contextual menu button for the message
  27. let menuButton = node.querySelector('._ahkm'); // Selector for the contextual menu button
  28.  
  29. // If it's not found, try another selector (in case of changes in the structure)
  30. if (!menuButton) {
  31. menuButton = node.querySelector('[role="button"][aria-label="Context menu"]');
  32. }
  33.  
  34. if (menuButton) {
  35. menuButton.click(); // Open the options menu
  36. }
  37.  
  38. // Make the message blink
  39. blinkMessage(node);
  40. });
  41. }
  42. }
  43.  
  44. function blinkMessage(node) {
  45. // Add the class that causes the blinking effect
  46. node.classList.add('blink');
  47.  
  48. // Remove the class after a short period (blinking)
  49. setTimeout(function() {
  50. node.classList.remove('blink');
  51. }, 500); // The message will blink for 500ms
  52. }
  53.  
  54. // CSS style for blinking
  55. const style = document.createElement('style');
  56. style.innerHTML = `
  57. .blink {
  58. animation: blink 0.5s alternate;
  59. }
  60.  
  61. @keyframes blink {
  62. 0% {
  63. opacity: 1;
  64. }
  65. 50% {
  66. opacity: 0;
  67. }
  68. 100% {
  69. opacity: 1;
  70. }
  71. }
  72. `;
  73. document.head.appendChild(style);
  74.  
  75. // Observe the chat container for new messages
  76. const observer = new MutationObserver(mutations => {
  77. mutations.forEach(mutation => {
  78. mutation.addedNodes.forEach(node => {
  79. if (node.nodeType === 1) { // Ensure it's an element
  80. attachContextMenuHandler(node);
  81. node.querySelectorAll('.message-out, .message-in').forEach(attachContextMenuHandler);
  82. }
  83. });
  84. });
  85. });
  86.  
  87. observer.observe(document.body, { childList: true, subtree: true });
  88. })();