Chat GPT scroll to the top and bottom buttons

Adds buttons to scroll to the top and bottom of the chat on Chat GPT

目前为 2024-08-23 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Chat GPT scroll to the top and bottom buttons
  3. // @author NWP
  4. // @description Adds buttons to scroll to the top and bottom of the chat on Chat GPT
  5. // @namespace https://greasyfork.org/users/877912
  6. // @version 0.3
  7. // @license MIT
  8. // @match https://chatgpt.com/*
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. function createButton(onClick, triangleDirection) {
  16. const button = document.createElement('button');
  17. const buttonStyle = `
  18. background-color: #707070;
  19. border: none;
  20. border-radius: 0.5em;
  21. cursor: pointer;
  22. display: flex;
  23. align-items: center;
  24. justify-content: center;
  25. width: 3.5em;
  26. height: 2em;
  27. position: relative;
  28. transition: background-color 0.3s;
  29. `;
  30. button.setAttribute('style', buttonStyle);
  31. button.addEventListener('click', onClick);
  32.  
  33. const triangle = document.createElement('div');
  34. const triangleStyle = `
  35. width: 0;
  36. height: 0;
  37. border-left: 0.75em solid transparent;
  38. border-right: 0.75em solid transparent;
  39. `;
  40. if (triangleDirection === 'up') {
  41. triangle.setAttribute('style', triangleStyle + 'border-bottom: 0.75em solid black;');
  42. } else {
  43. triangle.setAttribute('style', triangleStyle + 'border-top: 0.75em solid black;');
  44. }
  45. button.appendChild(triangle);
  46.  
  47. button.onmouseenter = function() {
  48. button.style.backgroundColor = '#9f9f9f';
  49. };
  50. button.onmouseleave = function() {
  51. button.style.backgroundColor = '#707070';
  52. };
  53.  
  54. return button;
  55. }
  56.  
  57. function scrollToTop() {
  58. const target = Array.from(document.querySelectorAll('div[class^="react-scroll-to-bottom--css"]')).filter(el => !el.className.includes('full'))[0];
  59. if (target) target.scrollTop = 0;
  60. }
  61.  
  62. function scrollToBottom() {
  63. const target = Array.from(document.querySelectorAll('div[class^="react-scroll-to-bottom--css"]')).filter(el => !el.className.includes('full'))[0];
  64. if (target) target.scrollTop = target.scrollHeight;
  65. }
  66.  
  67. function createButtons() {
  68. if (document.querySelector('div[part="scroll-buttons"]')) return;
  69.  
  70. const shadowHost = document.createElement('div');
  71. shadowHost.style.position = 'fixed';
  72. shadowHost.style.bottom = '3em';
  73. shadowHost.style.right = '2em';
  74. shadowHost.style.zIndex = '1000';
  75. shadowHost.setAttribute('part', 'scroll-buttons');
  76. document.body.appendChild(shadowHost);
  77.  
  78. const shadowRoot = shadowHost.attachShadow({ mode: 'closed' });
  79.  
  80. const container = document.createElement('div');
  81. container.style.display = 'flex';
  82. container.style.flexDirection = 'column';
  83. container.style.alignItems = 'center';
  84. container.style.gap = '0.25em';
  85. shadowRoot.appendChild(container);
  86.  
  87. const topButton = createButton(scrollToTop, 'up');
  88. container.appendChild(topButton);
  89.  
  90. const bottomButton = createButton(scrollToBottom, 'down');
  91. container.appendChild(bottomButton);
  92. }
  93.  
  94. function ensureButtonsDrawn() {
  95. createButtons();
  96.  
  97. const interval = setInterval(function() {
  98. if (document.querySelector('div[part="scroll-buttons"]')) {
  99. clearInterval(interval);
  100. } else {
  101. createButtons();
  102. }
  103. }, 1000);
  104. }
  105.  
  106. document.addEventListener('visibilitychange', function() {
  107. if (document.visibilityState === 'visible') {
  108. ensureButtonsDrawn();
  109. }
  110. });
  111.  
  112. window.addEventListener('load', function() {
  113. setTimeout(ensureButtonsDrawn, 500);
  114. });
  115. })();