如何在自定义处理的输入字段中输入数据?

How can I enter data into a custom-handled input field?

提问人:avalanche1 提问时间:9/11/2019 最后编辑:double-beepavalanche1 更新时间:10/26/2023 访问量:5848

问:

我的扩展有一个包含项目的上下文菜单。我希望它做的是:当我右键单击 HTML 元素(例如输入或文本区域)时,然后选择并单击菜单中的项目 - 我的扩展定义的一些值被输入到输入中。editable

现在我已经意识到:

document.activeElement.value = myValue

使用简单的输入就可以了。

当存在具有自定义事件处理功能的输入(例如日历或电话输入)或货币输入时,问题就开始了,这些输入以某种方式转换了用户输入。onChange

由于我直接在元素上设置了一个值 - 处理逻辑被省略了,这会导致各种问题。

由于 JavaScript 不允许类似 KeySend 的功能 - 我在这里有什么选择?

我曾考虑过测试像 Puppeteer 或 Cypress 这样的工具——但它们似乎都无法打包到扩展中。Puppeteer 确实有这样的选项,但它仍然需要运行一个节点实例才能连接到。我希望我的扩展程序完全是客户端的,并在 Chrome 网上商店中分发 - 所以我不能要求我的用户启动节点服务器。

javascript 谷歌浏览器扩展

评论


答:

47赞 wOxxOm 9/12/2019 #1

有一个内置的 DOM 方法 document.execCommand
如果是扩展,请在内容脚本中使用此代码。

// 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

它模仿物理用户输入到当前聚焦的 DOM 元素中,因此所有必要的事件都将被触发(如 、 ),字段设置为 true。在某些页面上,应按如上所示额外调度事件。beforeinputinputisTrustedchange

您可能希望选择当前文本以完全替换它,而不是附加:

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

function replaceValue(selector, value) {
  const el = document.querySelector(selector);
  if (el) {
    el.focus();
    document.execCommand('selectAll');
    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;
}

请注意,尽管 execCommand 在 2020 年被标记为过时,但它在可预见的未来将起作用,因为新的编辑 API 规范尚未完成,并且知道这些东西通常移动得有多慢可能需要 5-20 年。

10赞 John Wu 10/29/2021 #2

因为已被掠夺,我现在使用以下运行良好的代码:document.execCommand()

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

以下代码只能在普通网站上工作,但对于强势网站(例如Facebook)无效。

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

评论

0赞 ricks 6/22/2022
在 execCommand 弃用后解决这个问题的绝佳答案。
0赞 Daniel Ehrhardt 3/22/2023
但不适用于 Angular