You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chrome扩展推文回复问题:如何在无textarea的div弹窗中输入内容并触发回复

Hey there, let's work through this problem together! You've already nailed clicking the reply icon, but the tricky part is dealing with that contenteditable div instead of a standard textarea. Here's how to get your reply text in there and hit that reply button:

Solution for Inputting Text into Twitter/X's Reply Div & Triggering Reply

1. Target the Contenteditable Input Div

Twitter/X uses a contenteditable div for reply inputs (instead of a textarea) to support rich text formatting. After clicking the reply icon, wait for the modal to load (it's dynamic), then target this div with a reliable selector:

const replyInput = document.querySelector('div[contenteditable="true"][role="textbox"]');

2. Insert Your Reply Text

You can't use .value here like you would with a textarea. Instead, focus the div, set its text content, and trigger an input event so Twitter recognizes the text (this is key to enabling the reply button):

if (replyInput) {
  // Focus the input to activate it
  replyInput.focus();
  // Clear any placeholder text
  replyInput.textContent = '';
  // Insert your custom reply
  replyInput.textContent = 'Your awesome reply goes here!';
  // Dispatch an input event to let Twitter know content changed
  const inputEvent = new Event('input', { bubbles: true });
  replyInput.dispatchEvent(inputEvent);
}

3. Click the Reply Button

Once your text is in place, find and click the enabled reply button. Using the data-testid attribute is more reliable than class names (since Twitter changes those often):

const replyButton = document.querySelector('div[data-testid="tweetButton"]');
if (replyButton && !replyButton.disabled) {
  replyButton.click();
}

4. Full Working Code (With Dynamic Element Waiting)

Since the reply modal loads after clicking the icon, we need to wait for elements to exist instead of using flaky setTimeout. Here's the full code combining your existing click logic with the new input/button logic:

// Helper function to wait for a dynamic element to appear
function waitForElement(selector, timeout = 5000) {
  return new Promise((resolve, reject) => {
    // Check if element exists immediately
    const element = document.querySelector(selector);
    if (element) {
      resolve(element);
      return;
    }

    // Use MutationObserver to watch for element additions
    const observer = new MutationObserver(() => {
      const element = document.querySelector(selector);
      if (element) {
        observer.disconnect();
        resolve(element);
      }
    });

    observer.observe(document.body, { childList: true, subtree: true });

    // Timeout if element never appears
    setTimeout(() => {
      observer.disconnect();
      reject(new Error(`Element "${selector}" not found within timeout`));
    }, timeout);
  });
}

// Your existing code to locate and click the reply icon
var articles = $("article"); 
var reply_array = []; 
articles.each(function (increment, current) { 
  var reply_g = ""; 
  for (var i = 0; i < $(current).find("svg").length; i++) { 
    reply_g = $(current).find("svg g path").eq(i).attr("d"); 
    if ( reply_g == "M14.046 2.242l-4.148-.01h-.002c-4.374 0-7.8 3.427-7.8 7.802 0 4.098 3.186 7.206 7.465 7.37v3.828c0 .108.044.286.12.403.142.225.384.347.632.347.138 0 .277-.038.402-.118.264-.168 6.473-4.14 8.088-5.506 1.902-1.61 3.04-3.97 3.043-6.312v-.017c-.006-4.367-3.43-7.787-7.8-7.788zm3.787 12.972c-1.134.96-4.862 3.405-6.772 4.643V16.67c0-.414-.335-.75-.75-.75h-.396c-3.66 0-6.318-2.476-6.318-5.886 0-3.534 2.768-6.302 6.3-6.302l4.147.01h.002c3.532 0 6.3 2.766 6.302 6.296-.003 1.91-.942 3.844-2.514 5.176z" ) { 
      var uniq_id = uniqID(20); 
      $(current).find("svg").eq(i).parent().addClass(uniq_id); 
      reply_array.push(uniq_id); 
    } 
  } 
}); 
$(" ." + reply_array[0]).trigger("click");

// Handle the reply input and button after modal loads
waitForElement('div[contenteditable="true"][role="textbox"]')
  .then(replyInput => {
    replyInput.focus();
    replyInput.textContent = 'Your custom reply text here!';
    // Trigger input event to enable the reply button
    replyInput.dispatchEvent(new Event('input', { bubbles: true }));
    // Wait for the reply button to become enabled
    return waitForElement('div[data-testid="tweetButton"]:not([disabled])');
  })
  .then(replyButton => {
    replyButton.click();
    console.log('Reply sent successfully!');
  })
  .catch(err => {
    console.error('Error handling reply:', err);
  });

Quick Notes:

  • Selector Reliability: Twitter/X frequently updates its DOM, so using data-testid attributes (like data-testid="tweetButton") is more stable than relying on SVG paths or class names.
  • Permissions: Make sure your extension's manifest.json includes permission for https://x.com/* (or https://twitter.com/* if you're targeting the old domain).
  • Input Event: Don't skip dispatching the input event—Twitter's UI uses this to detect content changes and enable the reply button.

内容的提问来源于stack exchange,提问作者Junaid Rehman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 15:12:49