Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enter data into a custom-handled input field

My extension has a context menu with items. What I'd like it to do: is when I right-click an editable html element (eg input or textarea) and then select and click on an item in my menu - some value defined by my extension gets entered into the input.

For now I have realised that with document.activeElement.value = myValue.
With simple inputs it works alright.

Problems start when there is an input with custom onChange event handling, eg a calendar or a phone input, or currency input - that transforms user-input in some way.
Since I am setting a value directly onto the element - the handling logic gets omitted, which causes all manner of problems.

Since javascript doesn't allow for KeySend-like features - what are my options here?

I have thought about testing tools like Puppeteer or Cypress - but they all seem not to be packageable into an extension. Puppeteer does have such an option, but it still requires a node instance running to connect to. And I would like my extension to be solely client-sided and distributed in Chrome webstore - so I cannot ask my users to spin up a node server.

like image 442
avalanche1 Avatar asked Sep 10 '19 23:09

avalanche1


People also ask

How do I copy values from one input field to another?

Simply register an input even handler with the source textfield and copy the value to the target textfield .

How do you get the data from the textbox which is inputted by the user?

To extract the information which a user enters into the text fields using Javascript, the Javascript code to do would be: The line document. getElementById("firstname"). value accesses the text box with an id of firstname and retrieves the value which the user has entered into this text box.


2 Answers

There is a built-in DOM method document.execCommand.
In case of an extension, use this code in the content script.

// some.selector may be `input` or `[contenteditable]` for richly formatted inputs
const el = document.querySelector('some.selector');
el.focus();
document.execCommand('insertText', false, 'new text');
el.dispatchEvent(new Event('change', {bubbles: true})); // usually not needed

It imitates physical user input into the currently focused DOM element so all the necessary events will be fired (like beforeinput, input) with isTrusted field set to true. On some pages the change event should be additionally dispatched as shown above.

You may want to select the current text to replace it entirely instead of appending:

replaceValue('some.selector', 'new text');

function replaceValue(selector, value) {
  const el = document.querySelector(selector);
  if (el) {
    el.focus();
    el.select();
    if (!document.execCommand('insertText', false, value)) {
      // Fallback for Firefox: just replace the value
      el.value = 'new text';
    }
    el.dispatchEvent(new Event('change', {bubbles: true})); // usually not needed
  }
  return el;
}

Note that despite execCommand being marked as obsolete in 2020, it'll work in the foreseeable future because a new editing API specification is not finished yet, and knowing how slow such things usually move it may take another 5-20 years.

like image 118
wOxxOm Avatar answered Oct 17 '22 09:10

wOxxOm


@wOxxOm, thank you very much ! I used your code solved my problem which has bothered me for long time. I googled many code and article for nearly one month. It works on Facebook and many strong website.

Because execCommand has depredated, I try below code it works well, include Facebook.

function imitateKeyInput(el, keyChar) {
  if (el) {
    const keyboardEventInit = {bubbles:false, cancelable:false, composed:false, key:'', code:'', location:0};
    el.dispatchEvent(new KeyboardEvent("keydown", keyboardEventInit));
    el.value = keyChar;
    el.dispatchEvent(new KeyboardEvent("keyup", keyboardEventInit));
    el.dispatchEvent(new Event('change', {bubbles: true})); // usually not needed
  } else {
    console.log("el is null");    
  }
}

The following code can only work on ordinary websites, but it is invalid for strong website.

function fireKeyEvent(el, evtType, keyChar) {
  el.addEventListener(evtType, function(e) {el.value += e.key;}, false);
  el.focus();
  const keyboardEventInit = {bubbles:false, cancelable:false, composed:false, key:keyChar, code:'', location:0};
  var evtObj = new KeyboardEvent(evtType, keyboardEventInit);
  el.dispatchEvent(evtObj);
}
like image 32
John Wu Avatar answered Oct 17 '22 07:10

John Wu