admin管理员组

文章数量:1310185

I am trying to set a value for the textbox on a PayPal Giving Fund donation page and am thoroughly stumped.

Here's what I've tried:

Setting input.value

From Chrome devtools, if I run the following JavaScript:

document.getElementById('nemo_inputAmount').value = '1'

The value '1' appears in the textbox, but when I click the "Donate Now" button, the value is cleared and the form does not submit.

Sending events

I used Chrome devtools to monitor all of the events when I tabbed into the textbox, typed the value '1', and tabbed out.

Then I recreated each of those events using the code below. The value '1' does not even appear in the textbox using this approach. I have tried every bination and style of dispatching events that I can think of.

function textEvent(text) {
  let textEvent = document.createEvent('TextEvent');
  textEvent.initTextEvent('textInput', true, true, null, text);
  return textEvent;
}

function setDonationAmount(amount) {
  let amountInput = document.querySelector('input#nemo_inputAmount');

  if (amountInput) {
    console.log('Setting amount to', amount)

    const events = [
      new FocusEvent('focus', {
        posed: true
      }),
      new Event('select', {
        bubbles: true
      }),
      new KeyboardEvent('keydown', {
        bubbles: true,
        cancelable: true,
        posed: true,
        code: 'Digit1',
        key: '1',
        keyCode: 49,
        which: 49
      }),
      new KeyboardEvent('keypress', {
        bubbles: true,
        cancelable: true,
        posed: true,
        code: 'Digit1',
        key: '1',
        keyCode: 49,
        which: 49
      }),
      textEvent('1'),
      new Event('input', {
        bubbles: true
      }),
      new KeyboardEvent('keyup', {
        bubbles: true,
        cancelable: true,
        posed: true,
        code: 'Digit1',
        key: '1',
        keyCode: 49,
        which: 49
      }),
      new Event('change', {
        bubbles: true
      }),
      new FocusEvent('blur', {
        posed: true
      })
    ]

    events.forEach(function(event) {
      amountInput.dispatchEvent(event);
    })
  }
}

setDonationAmount('1');

As you can see, I'm trying to do this in pure JavaScript. I'm pletely baffled why neither of the solutions above work.

Does anyone have any suggestions?

I am trying to set a value for the textbox on a PayPal Giving Fund donation page and am thoroughly stumped.

Here's what I've tried:

Setting input.value

From Chrome devtools, if I run the following JavaScript:

document.getElementById('nemo_inputAmount').value = '1'

The value '1' appears in the textbox, but when I click the "Donate Now" button, the value is cleared and the form does not submit.

Sending events

I used Chrome devtools to monitor all of the events when I tabbed into the textbox, typed the value '1', and tabbed out.

Then I recreated each of those events using the code below. The value '1' does not even appear in the textbox using this approach. I have tried every bination and style of dispatching events that I can think of.

function textEvent(text) {
  let textEvent = document.createEvent('TextEvent');
  textEvent.initTextEvent('textInput', true, true, null, text);
  return textEvent;
}

function setDonationAmount(amount) {
  let amountInput = document.querySelector('input#nemo_inputAmount');

  if (amountInput) {
    console.log('Setting amount to', amount)

    const events = [
      new FocusEvent('focus', {
        posed: true
      }),
      new Event('select', {
        bubbles: true
      }),
      new KeyboardEvent('keydown', {
        bubbles: true,
        cancelable: true,
        posed: true,
        code: 'Digit1',
        key: '1',
        keyCode: 49,
        which: 49
      }),
      new KeyboardEvent('keypress', {
        bubbles: true,
        cancelable: true,
        posed: true,
        code: 'Digit1',
        key: '1',
        keyCode: 49,
        which: 49
      }),
      textEvent('1'),
      new Event('input', {
        bubbles: true
      }),
      new KeyboardEvent('keyup', {
        bubbles: true,
        cancelable: true,
        posed: true,
        code: 'Digit1',
        key: '1',
        keyCode: 49,
        which: 49
      }),
      new Event('change', {
        bubbles: true
      }),
      new FocusEvent('blur', {
        posed: true
      })
    ]

    events.forEach(function(event) {
      amountInput.dispatchEvent(event);
    })
  }
}

setDonationAmount('1');

As you can see, I'm trying to do this in pure JavaScript. I'm pletely baffled why neither of the solutions above work.

Does anyone have any suggestions?

Share Improve this question asked Feb 28, 2017 at 14:33 Erik GillespieErik Gillespie 3,9592 gold badges33 silver badges48 bronze badges 5
  • Are all the preconditions of form submission met? Missing any required fields? – Jared Smith Commented Feb 28, 2017 at 14:37
  • 1 Try document.execCommand as shown here. – woxxom Commented Feb 28, 2017 at 14:43
  • @JaredSmith Aside from some buttons that set fixed donation amounts, this textbox is the only form element on the page. – Erik Gillespie Commented Feb 28, 2017 at 14:43
  • @wOxxOm That works! Please add your ment as an answer so I can accept it! :) – Erik Gillespie Commented Feb 28, 2017 at 14:49
  • 1 I doubt I should add an identical answer. AFAIK in such cases the question is considered a duplicate. – woxxom Commented Feb 28, 2017 at 14:53
Add a ment  | 

2 Answers 2

Reset to default 5

The input is part of a React ponent. I was able to find this by searching the source for the ID of the input (nemo_inputAmount). This search took me to the render function for the ponent. Here's the relevant section of it:

_react2.default.createElement('input', {
  type: 'text',
  id: 'nemo_inputAmount',
  className: inputBoxStyling,
  onChange: this.handleInputChange,
  onFocus: this.handleInputFocus,
  value: this.state.inputAmount,
  autoComplete: 'off',
  placeholder: 'Other Amount',
  required: true
}),

You can see the event handlers on it: onChange and onFocus. The handlers are defined earlier on. Here are the snippets:

handleInputChange: function handleInputChange(event) {

  var value = event.target.value;
  var input = (0, _parseAmount2.default)(value);
  if (input === undefined) {
    return this.invalid();
  }

  this.setState({
    inputAmount: input
  });
},

handleInputFocus: function handleInputFocus() {
  this.setState({
    selectedAmount: '',
    radioBtnClicked: false,
    clickedIndex: -1
  });
},

You can see that when the input changes it changes the inputAmount in the store to the new amount. If you look back to the createElement function you can see the inputAmount in the store is bound to the value attribute of the input.

  value: this.state.inputAmount,

This means the value of the input is set when the event handler is only run when the relevant event is fired.

Setting the value attribute programmatically does not fire the event, which is why your input kept clearing because the store wasn't updated so it was still empty.

To make it work you will need this:

const input = document.getElementById('nemo_inputAmount');
const event = new Event('input', { bubbles: true });
input.value = '1';
input.dispatchEvent(event);

This part creates a new input event, which is the event that handleInputChange actually reacts to – I haven't looked at the React source to confirm, this statement is based on observations and this Stack Overflow answer.

const event = new Event('input', { bubbles: true });

This part then dispatches the event.

input.dispatchEvent(event);

This is the only thing that worked for me, works in Edge:

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);
  }
}

Use it like so:

setNativeValue(textarea, 'some text');
textarea.dispatchEvent(new Event('input', { bubbles: true }));

Obtained from here: https://github./facebook/react/issues/10135#issuement-314441175

本文标签: