如何在没有 ID 的情况下将文本插入 JavaScript 中的选定文本框?

How to insert text into selected textbox in JavaScript without ID?

上下文:

  1. 使用 JavaScript
  2. 编写 google chrome 扩展
  3. 使用上下文菜单库
  4. 用户应该可以右键单击文本框 select chrome 扩展名 select "insert text",然后该文本将插入到 selected 文本框。
  5. 我正在使用纯 javascript,请不要使用 jquery 或 AJAX。
  6. 我无法编辑 HTML 页面,因为它可能是任何带有 HTML 文本框或可编辑字段的通用网页。

我目前拥有的代码:

//the menu item
    var menuItem_insert = chrome.contextMenus.create({"title": "Insert Timestamp", "contexts":[context], "onclick:": insertTimestamp}); 

//the onclick
    function insertTimestamp(info, tab) {
      //if info.editable is true then
      alert(info.editable); //for debugging

    //CODE GOES HERE: need to insert timestamp here
    }

问题: 如何将文本插入 selected 文本框,而我可能没有 "ID"?

通过document.activeElement可以引用当前活动元素:

document.activeElement.value = 'My value';

应该将 "My value" 字符串放入您在调用时选择的输入文本中。

不幸的是,在您的情况下,您希望在单击按钮后发生这种情况,因此您的活动元素将在单击时成为您的按钮。 因此,您可以找到解决方法来定义文本输入的元素 onblur,以便单击按钮时您将引用该输入文本。 所以这是 HTML

<div>
  <input type="text" onblur="trackElement(this)" />
  <button onclick="test()">
  Test
  </button>
</div>

这是 JS:

var myTxt = null;

function test() {
    if (myTxt != null) {
    myTxt.value = 'my value';
  }
}

function trackElement(el) {
    console.log(el);
    myTxt = el;
}

https://jsfiddle.net/2459g8z5/4/

according this reply
您可以使用 mousedown 事件侦听器注入内容脚本并存储被单击的元素:

manifest.json

..
"permissions": ["contextMenus"],
"background": {
  "scripts": ["./bg.js"]
},
"content_scripts": [{
  "js": ["./content.js"],
  "matches": ["<all_urls>", "http://*/*" , "https://*/*", "file:///"],
  "run_at": "document_end"
}],
"manifest_version": 2
..

background.js

function mycallback(info, tab) {
  if (info.editable) {
    chrome.tabs.sendMessage(tab.id, {
      "text": "TEXT GOES HERE"
    });
  }
}
chrome.contextMenus.create({
  title: "Insert Timestamp",
  contexts: ["editable"],
  onclick: mycallback
});

content.js

var clickedEl = null;
document.addEventListener("mousedown", function (event) {
  //right click
  if (event.button == 2) {
    clickedEl = event.target;
  }
}, true);
chrome.runtime.onMessage.addListener(function (request) {
  clickedEl.value = request.text;
});

回答的不错,这是另一种解决问题的方法

逻辑是,当用户单击您的上下文菜单项时,菜单将消失并且焦点回到您需要的位置,在开始右键单击的原始元素上 (也可以从该元素中的任何点开始如果用户点击了现有文本中间的某处)
您需要做的就是模拟 copy/paste 动作。

所以,在后台脚本中:

  • 在您的 onClicked 侦听器中创建 textarea
  • 用您要插入的值填充它(本例中为日期字符串)
  • 聚焦它 select 它
  • 使用 document.execCommand('Copy')taxarea 值放入剪贴板
  • 如果点击是从 iframe 开始的,请确保您只针对该框架,以避免多个脚本插入和错误
  • 将脚本注入发件人选项卡(您拥有来自 onClicked 侦听器的所有信息)
  • 注入的脚本只会做一件事,粘贴剪贴板中的内容document.execCommand('paste')

background.js

chrome.contextMenus.onClicked.addListener(function(info, tab) {
    var tArea = document.createElement('textarea'), _frame = null, date = new Date();
    document.body.appendChild(tArea);
    tArea.value = date.toLocaleString();
    tArea.focus();
    tArea.select();
    document.execCommand('copy');

    if(info.frameId) _frame = info.frameId;

    chrome.tabs.executeScript(tab.id, {frameId: _frame, matchAboutBlank: true, code: 
        "document.execCommand('paste');"
    }, function() {
        if (chrome.runtime.lastError) console.log(chrome.runtime.lastError);
        document.body.removeChild(tArea);
    });     
});

在您的清单中添加"clipboardWrite", "clipboardRead", "activeTab"权限

我在 Opera notes extension 中使用了这个逻辑。
我从未见过有人使用过这个技巧,它非常简单,而且它会消除所有针对正确元素的麻烦,select离子、范围、富文本编辑器等