Javascript 是否有灵活的方法修改可编辑元素的内容? 主题:

Javascript 是否有灵活的方法修改可编辑元素的内容? 主题:,javascript,html,dom,text,google-chrome-extension,Javascript,Html,Dom,Text,Google Chrome Extension,我正在创建一个GoogleChrome扩展,它通过内容脚本和事件页面与网页交互 我有一个上下文菜单选项,当用户单击一个元素,该元素被 这些选项类似于常用输入文本的快捷方式。当用户单击某个选项时,某些文本将放置在元素内部光标位置。如果用户突出显示了文本,则会将其删除 问题: 并非所有可编辑图元都可以以相同的方式修改 如果元素是一个简单的textarea,则可以通过实施此解决方案来实现所需的结果: 但是,我不能假设我正在与正常的textarea进行交互 可能的细微差别包括: 隐藏在Ifra

我正在创建一个GoogleChrome扩展,它通过内容脚本和事件页面与网页交互

我有一个上下文菜单选项,当用户单击一个元素,该元素被

这些选项类似于常用输入文本的快捷方式。当用户单击某个选项时,某些文本将放置在元素内部光标位置。如果用户突出显示了文本,则会将其删除


问题: 并非所有可编辑图元都可以以相同的方式修改

如果元素是一个简单的
textarea
,则可以通过实施此解决方案来实现所需的结果:

但是,我不能假设我正在与正常的
textarea
进行交互

可能的细微差别包括:

  • 隐藏在
    Iframe
    中的文本区域,这使查找要与之交互的元素的过程复杂化(
    document.activeElement
    可能返回
    Iframe
    ,而不是实际包含文本的元素)

  • 根本不是一个
    /
    ,而是一个。
    .value
    方法在这种情况下不起作用

因此,我正在寻找一种灵活的方法来做到这一点,可以优雅地处理所有边缘情况


我尝试过一些解决方案:
  • 选项1:
    我最初计划将值存储在系统剪贴板中。然后,我可以想象使用
    document.execCommand('paste')
    修改元素。然而,在尝试之后,这种方法似乎与我最初的方法有相同的缺点。(请参阅)

    此外,此方法将删除操作前剪贴板中的任何内容。这是不可取的,任何使用此方法的解决方案都必须提供解决方案。

  • 选项2:
    我考虑过的另一个选项是为字符串中的每个字符分配键盘事件。但是,使用此解决方案,您仍然会遇到
    Iframe
    问题,并且它不允许您使用特殊的Unicode字符。┻━┻ ︵ヽ(`Д´)ノ︵ ┻━┻
您的问题由两个子问题组成:

  • 确定contextmenu操作的目标元素
  • 在插入符号处插入自定义文本片段(如果存在任何选择,请将其删除)
  • 子问题1:识别目标元素
    • 如果已解决,则获取元素很容易。这个功能请求已经有5年了,没有任何进展,所以不要对它寄予厚望。 替代方法要求您将问题1分解为另外两个子问题:识别目标帧,然后选择目标DOM元素
    有几种API有助于识别框架(使用它们的组合,选择最适合您情况的组合):

    • 该事件将选项卡的ID(
      tab.ID
      )作为实例中的属性提供,并将框架的URL()作为单独对象中的属性提供
    • 该方法可以在一个帧中直接运行脚本。
      (目前,针对特定帧的顶层帧或所有帧正在进行中,计划用于Chrome 42)。
      在实现针对特定帧之前,您可以在每个帧中插入内容脚本,并将URL与
      frameUrl
      (或使用以下方法的组合)进行比较
    • 假设您已经插入了带有侦听器的内容脚本,则使用将消息发送到由
      frameId
      标识的特定帧(从Chrome 41开始)
    • 使用该方法获取给定
      tabId
      选项卡中所有帧的列表,然后通过已知
      frameUrl
      过滤帧列表,获取目标帧的
      frameId
    • (在将来(Chrome 42?),单击上下文菜单将获得
      frameId
    好的,假设您有正确的框架,您可以简单地使用
    document.activeElement
    获取目标元素,因为输入元素在单击时会聚焦

    子问题2:在插入符号处插入文本片段 如果目标元素是
    ,则只需使用

    //假设:elem是一个input或textarea元素。
    var YOURSTRING='whatever';
    var start=elem.selectionStart;
    var end=elem.selectionEnd;
    elem.value=elem.value.slice(0,开始)+YOURSTRING+elem.value.substr(结束);
    //在选定文本后设置光标
    elem.selectionStart=start+YOURSTRING.length;
    elem.selectionEnd=elem.selectionStart;
    
    否则,您需要知道是否存在内容可编辑元素,如果存在,请删除任何选择(如果存在),最后将所需文本放在那里

    var elem=document.activeElement;
    if(elem&&elem.isContentEditable){
    //您的字符串与前面定义的相同
    var newNode=document.createTextNode(您的字符串);
    var sel=window.getSelection();
    //删除以前的选择(如果有)。
    sele.deleteFromDocument();
    //如果选择中没有范围,请使用
    //插入符号设置为输入元素的结尾,以避免出现下一个错误:
    //未能对“选择”执行“getRangeAt”:0不是有效索引
    如果(sel.rangeCount==0){
    sel.addRange(document.createRange());
    选择范围(0)。折叠(元素1);
    }
    //插入新文本
    var范围=选择范围(0);
    range.insertNode(newNode);
    //现在,将光标设置到文本节点的末尾
    选择折叠(newNode,1);
    }
    
    上一个示例中使用的web平台API的相关文档:


    我将为这场静默增加一笔赏金(我个人觉得这很有趣,也不明显)