grok Paste

Paste text into Grok textarea from main page

// ==UserScript==
// @name         grok Paste
// @description  Paste text into Grok textarea from main page
// @match        *://grok.com/*
// @version 0.0.1.20250809090131
// @namespace https://greasyfork.org/users/1435046
// ==/UserScript==

(function () {
  'use strict';

  let queueArray = [];
  let cycleInProgress = false;
  let responseCompleted = false;

  window.addEventListener("message", event => {
    const data = event.data;

    if (event.data && event.data.type === 'reasonButtonClicked') {
      document.querySelector('button[aria-label="Think"]').click();
      return;
    }

    if (event.data?.type === 'newChatButtonClicked') {
      const customNewChatButton = document.querySelector('a[href="/"]');
      if (customNewChatButton) customNewChatButton.click();
    }

    //grab style element
    let grokCssStyleId = document.getElementById('grokCssStyleId');

    let chatMessageInput = document.querySelector('div:has(> div > form > div > div > div > textarea[aria-label="Ask Grok anything"])');
    let chatMessageInputRule = 'div:has(> div > form > div > div > div > textarea[aria-label="Ask Grok anything"]) {display: none !important;}';


    let chatMessageInputBackdrop = document.querySelector('.chat-input-backdrop');
    let chatMessageInputBackdropRule = '.chat-input-backdrop {display: none !important;}';
    let header = document.querySelector('div:has(> div > div > button[aria-label="Toggle sidebar"] > svg > path[d="M3 12h18"])');

    //if event data type is defaultChatMessageInputDisplay
    if (event.data?.type === 'defaultChatMessageInputDisplay') {
      console.log('default');
      if (chatMessageInput) {

        //delete the rule here
        grokCssStyleId.innerHTML = grokCssStyleId.innerHTML.replace(`${chatMessageInputRule}`, '')
        grokCssStyleId.innerHTML = grokCssStyleId.innerHTML.replace(`${chatMessageInputBackdropRule}`, '')

        header.style.removeProperty('display');

        //return
        return;
      }
    }

    if (event.data?.type === 'customizeChatMessageInputDisplay') {
      console.log('customize');
      if (chatMessageInput) {

        grokCssStyleId.innerHTML += `${chatMessageInputRule}`

        grokCssStyleId.innerHTML += `${chatMessageInputBackdropRule}`

        header.style.display = 'none';

        //return
        return;
      }
    }


    if (event.data.type === "prompt" && event.data.content.trim()) {

      queueArray.push(event.data.content);

      console.log(cycleInProgress)

      function queue() {
        if (cycleInProgress || queueArray.length === 0) { return };

        cycleInProgress = true;
        const textarea = document.querySelector('textarea[aria-label="Ask Grok anything"]');
        if (!textarea) return;

        const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, "value").set;
        nativeInputValueSetter.call(textarea, queueArray[0]); // Set like the browser would

        // Now trigger a React-compatible InputEvent
        const inputEvent = new InputEvent('input', {
          bubbles: true,
          cancelable: true,
          inputType: 'insertText',
          data: queueArray[0],
        });

        textarea.dispatchEvent(inputEvent);

        document.querySelector('button[aria-label="Submit"]').click();
        const stopButtonSelector = 'button[aria-label="Stop model response"]';

        let observer = new MutationObserver(function (mutationRecordArray) {
          //for each mutation
          mutationRecordArray.forEach(function (mutationRecord) {

            mutationRecord.removedNodes.forEach((node) => {
              if (node.matches && node.matches(stopButtonSelector)) {
                console.log('button with aria label stop model response has been removed');
                responseCompleted = true;
                console.log('responseCompleted' + responseCompleted)
                //disconect the observer since the cycle has finished and a response has been generated
                observer.disconnect();
                //as the response has completed lets remove the first value in the queue which we presumably just got a
                //response for
                console.log(queueArray.shift())
                //lets indicate theat the cycle has ended
                cycleInProgress = false;
                //lets call the queue function again to see if there are more items in the queue array
                queue();
              };
            });
          })
        })
        observer.observe(document.body, { childList: true, subtree: true })
      }
      queue();
    }
  });
})();