Chrome扩展程序可以获得并设置插入位置

时间:2012-05-31 01:34:51

标签: javascript google-chrome google-chrome-extension contenteditable

在Google扩展程序中使用DOM

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

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

最初我尝试执行以下操作:

  1. 从当前插入位置插入文字
  2. 捕获插入位置。
  3. 根据偏移量设置插入位置。
  4. getSelection,不是那么快

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

    我发现 getSelection 代码不起作用的原因是因为在错误的窗口上选择了 document.getSelection 。在gmail中创建新邮件时,有5个iframe(窗口)可用。在此框架内有一个名为嵌套深度的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);
    

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

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

1 个答案:

答案 0 :(得分: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/master/asciimoji.jquery.js