简体   繁体   中英

Fill and submit textarea programmatically in javascript

I'm trying to automate the submission of replies to my Steemit posts using plain JS or Jquery.

I used the javascript code below but the button remains disabled and therefore does not allow to post the reply/comment.

How can I correctly trigger keydown / keypress / keyup events on the textarea in order to simulate the user "classic" interaction to send a reply?

Thanks


Target example: https://steemit.com/usa/@gaottantacinque/happy-4th-of-july

In the Dev Tools console:

function nap (durationMs) {
  new Promise(resolve => setTimeout(() => resolve(), durationMs))
}

async function replyToPost() {
  var replyBtn = document.getElementsByClassName("PostFull__reply")[0]
    .getElementsByTagName('a')[0];
  replyBtn.click();
  await nap(1000);
  var textarea = document.getElementsByTagName('textarea')[0];
  const msg = 'My programmatically generated comment goes here';
  textarea.focus();
  textarea.click();
  textarea.value = msg; // textarea.innerHTML = msg; textarea.innerText = msg;
  await nap(100);
  var postReplyBtn = document.querySelectorAll('[type=submit]')[1];
  // postReplyBtn.disabled = false;
  postReplyBtn.click();
}

replyToPost();

Notes: This code fills the textarea but the button is still disabled. Simply manually clicking on the textarea and typing anything the button gets enabled instead.

Also, the textarea value inserted programmatically disappears after clicking for instance on the background but it does not when entered normally.

After trying everything, I found out that the problem seems to be a bug in React on triggering onchange for textareas.

More info on the bug

There is a workaround..

Solution:

function setNativeValue(element, value) {
  const valueSetter = Object.getOwnPropertyDescriptor(element, 'value').set;
  const prototype = Object.getPrototypeOf(element);
  const prototypeValueSetter = Object.getOwnPropertyDescriptor(prototype, 'value').set;

  if (valueSetter && valueSetter !== prototypeValueSetter) {
    prototypeValueSetter.call(element, value);
  } else {
    valueSetter.call(element, value);
  }
}

var textarea = document.getElementsByTagName('textarea')[0];
setNativeValue(textarea, 'My automated comment here');
textarea.dispatchEvent(new Event('input', { bubbles: true }));

that might not work for some cases as it didn't for me but here's a general solution:

 const textarea = document.getElementsByTagName('textarea')[0]
function setNativeValue(element, value) {
  const { set: valueSetter } = Object.getOwnPropertyDescriptor(element, 'value') || {}
  const prototype = Object.getPrototypeOf(element)
  const { set: prototypeValueSetter } = Object.getOwnPropertyDescriptor(prototype, 'value') || {}

  if (prototypeValueSetter && valueSetter !== prototypeValueSetter) {
    prototypeValueSetter.call(element, value)
  } else if (valueSetter) {
    valueSetter.call(element, value)
  } else {
    throw new Error('The given element does not have a value setter')
  }
}
setNativeValue(textarea, 'some text')
textarea.dispatchEvent(new Event('input', { bubbles: true }))

i also wanna thank the previous person who posted about it ... it really helped a LOT

here is where i found it:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM