2

在 google 扩展程序中使用 DOM

我正在创建一个Google Chrome 扩展程序,我需要在其中将链接插入到gmail窗口中。我能够在窗口顶部创建一个简单的扩展按钮并执行替换电子邮件文档中元素的代码。

现在,我想在我键入时在contenteditable部分中添加链接。似乎应该有一种简单的方法来用 javascript 文档对象模型中的链接替换文本。这也只需要为 chrome 工作,因为我不打算很快创作一个 firefox 或 ie 版本。

最初我试图做以下事情:

  1. 从当前插入符号位置插入文本
  2. 捕获插入符号位置。
  3. 通过偏移量设置插入符号的位置。

getSelection,没那么快

我尝试在 gmail 上下文中使用window.getSelection(这是一个设置为 contenteditable 并嵌入到 gmail 选项卡中的 iframe 中的正文元素)来获取当前范围和位置。无论是否选择了文本,选择始终为空且不包含任何范围。

我发现getSelection代码不起作用的原因是因为在错误的窗口上选择了document.getSelection 。当您在 gmail 中创建新消息时,有 5 个 iframe(windows)可用。在这个框架内部有一个称为嵌套的 iframe,它需要调用getSelection才能获得正确的文本选择。这是一些代码,可让您在电子邮件的内容可编辑区域中获取选定的插入符号位置。

这是获取 gmail 文档窗口选择的一种方法

var mySelection = $("iframe")[4].contentDocument.
    querySelector("iframe").contentDocument.getSelection();

第一次文本替换尝试

我现在希望更接近解决方案。抱歉,如果草率,我找不到有关如何编写此代码的任何好的文档。

// Select the keyword
var range = s.getRangeAt(0);
var keyEl = range.startContainer.splitText(index);
var newRange = doc.createRange();
newRange.selectNode(keyEl);
s.removeAllRanges();
newRange.setEnd(keyEl, length);
s.addRange(newRange);

// Insert the link
var newLink = document.createElement("a");
newLink.setAttribute("href", value);
s.removeAllRanges();
newRange.surroundContents(newLink);

// Set the position
newRange.setStartAfter(newLink);
newRange.collapse(true);
s.addRange(newRange);

这几乎可以完美地工作,但问题是文本插入符号位于链接内,因此任何在此之后键入的文本都被插入到链接中。这是个大问题。而且,尝试了一些事情,我能够让这个问题部分消失。一个类似的新问题导致了一些奇怪的链接,这些链接延伸到以下单词,但仅限于几个字符。

希望是文本替换的最后尝试

// find position in text 
var index = s.focusNode.data.search(keyword);
var length = keyword.length;

var range = s.getRangeAt(0);
var keyEl = range.startContainer.splitText(index);
var newRange = doc.createRange();
newRange.selectNode(keyEl);
s.removeAllRanges();
newRange.setEnd(keyEl, length);
s.addRange(newRange);

var newLink = document.createElement("a");
newLink.setAttribute("href", value);
$(newLink).css("text-decoration", "none");
$(newLink).css("cursor", "pointer");
$(newLink).css("color", "color:#3366FF");
newRange.surroundContents(newLink);
newRange.collapse(false);
s.removeAllRanges();
s.addRange(newRange);

在我的许多试验中似乎普遍存在一个问题,现在已经消失了。这产生了一些奇怪的链接,这些链接延伸到以下单词。

随时帮我清理代码以使其更简洁

4

1 回答 1

0

如果您确切知道要插入插入符号的位置,则应该这样做:

var node = someTextNode;
var caret = 10; // insert caret after the 10th character
var range = document.createRange();
range.setStart(node,caret);
range.setEnd(node,caret);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);

然而,这仅适用于 DOM 文本节点。因此,如果您想操作 contenteditable div 或类似内容的内容,您将不得不递归遍历其子元素并检查文本节点。

我最近编写了一个 Chrome 扩展程序,可以在包括 GMail 在内的网站上进行文本替换 - 这是相应 jQuery 插件的来源,如果它适合您的用例,请随意利用它:https ://github.com/squidpeople/ASCIImoji/blob/大师/asciimoji.jquery.js

于 2013-07-29T17:35:20.373 回答