我正在创建一个Google Chrome扩展程序,通过内容脚本和活动页面与网页进行交互。
如果用户点击chrome.contextMenus
API归类为editable
的元素,则会显示上下文菜单选项。
这些选项就像常用文本的快捷方式一样。当用户单击选项时,某些文本将放置在光标位置的元素内。如果用户突出显示文本,则会将其删除。
并非所有可编辑元素都可以以相同方式修改。
如果元素是简单的textarea
,则可以通过实现此解决方案来实现所需的结果:
但是,我不能假设我正在与正常的textarea
进行交互。
可能的细微差别包括:
隐藏在Iframe
内的文本区域,使查找要与之交互的元素的过程变得复杂(document.activeElement
可能会返回Iframe
,而不是实际上包含文本)。
<textarea>
根本不是<textarea>
/ <input>
,而是contentEditable <div>
。在这种情况下,.value
方法不起作用。
所以我正在寻找一种灵活的方法,可以优雅地处理所有边缘情况。
document.execCommand('paste')
来修改元素。然而,在尝试之后,这种方法似乎与我最初的方法具有相同的缺点。 (参见this question)Iframe
问题,并且它不允许您使用特殊的Unicode字符。 ┻━┻(ヽ(`Д')ノ(┻━┻答案 0 :(得分:7)
您的问题包含两个子问题:
有几个API可以帮助识别框架(使用它们的组合,选择最适合您情况的组合):
contextMenus.onClicked
事件在单独的对象中将标签的ID(tab.id
)作为tabs.Tab实例中的属性和框架的网址(frameUrl
)提供。 / LI>
chrome.tabs.executeScript
方法可以直接在框架中运行脚本
(目前只有顶级框架或所有框架,针对特定框架正在进行中 - crbug.com/63979,计划用于Chrome 42)。frameUrl
进行比较(或使用下一种方法的组合)。chrome.runtime.onMessage
侦听器插入了内容脚本,请使用chrome.tabs.sendMessage
向frameId
标识的特定帧发送消息(自Chrome 41起)。chrome.webNavigation.getAllFrames
方法获取给定tabId
标签中所有框架的列表,然后通过过滤框架列表获取目标框架的frameId
已知frameUrl
。contextMenus.onClicked
将获得frameId
。好的,假设你有正确的框架,你只需使用document.activeElement
来获取目标元素,因为输入元素会在点击时集中。
如果目标元素是<textarea>
或<input>
,那么您只需使用
// Assume: elem is an input or textarea element.
var YOURSTRING = 'whatever';
var start = elem.selectionStart;
var end = elem.selectionEnd;
elem.value = elem.value.slice(0, start) + YOURSTRING + elem.value.substr(end);
// Set cursor after selected text
elem.selectionStart = start + YOURSTRING.length;
elem.selectionEnd = elem.selectionStart;
否则,您需要知道是否有内容可编辑元素,如果有,请删除任何选择(如果存在),最后将所需文本放在那里。
var elem = document.activeElement;
if (elem && elem.isContentEditable) {
// YOURSTRING as defined before
var newNode = document.createTextNode(YOURSTRING);
var sel = window.getSelection();
// Remove previous selection, if any.
sel.deleteFromDocument();
// If there is no range in the selection, add a new one, with the
// caret set to the end of the input element to avoid the next error:
//"Failed to execute 'getRangeAt' on 'Selection': 0 is not a valid index."
if (sel.rangeCount === 0) {
sel.addRange(document.createRange());
sel.getRangeAt(0).collapse(elem, 1);
}
// Insert new text
var range = sel.getRangeAt(0);
range.insertNode(newNode);
// Now, set the cursor to the end of your text node
sel.collapse(newNode, 1);
}
上一个示例中使用的Web平台API的相关文档: