【问题标题】:Chrome Selection.addRange() does not select (an execCommand('copy') use case)Chrome Selection.addRange() 不选择(一个 execCommand('copy') 用例)
【发布时间】:2017-07-16 22:47:33
【问题描述】:

在 Chrome 中编写一个小型浏览器扩展程序,将某些特定文本从特定网页复制到剪贴板。 HTML 格式,因此人们可以将其粘贴到 Word、Outlook 等办公程序中。

document.execCommand('copy') 是我使用的命令,它是由document.onkeydown 组合键 (Alt+1) 触发的,它工作正常 - 但只是第一次。如果您再次尝试按下组合键,它不会执行任何操作。

我找到了原因,document.queryCommandEnabled("copy") 第一次返回 true,任何其他尝试返回 false。如果我重新加载页面,它会第一次再次返回 true。此外,如果我在加载页面后在浏览器窗口外单击,然后在浏览器中单击并使用组合键,即使是第一次,也会立即返回 false。

function copy(text) {
  var sel = document.createElement("div"); // Creating temporary holder for text to copy

  sel.style.opacity = 0;             sel.style.position = "absolute";  // These are not really required,
  sel.style.pointerEvents = "none";  sel.style.zIndex = -1;            // at least for Chrome

  sel.innerHTML = text; // Put the text to copy into the temporary holder

  document.body.appendChild(sel); // Add the temporary holder to the page

  var range = document.createRange();     // All this is required to select the text,
  range.selectNode(sel);                  // since the holder is not an editable text
  window.getSelection().addRange(range);  // field and must be treated differently.

  // document.designMode = 'on'; (Tried this, no effect)

  /* Debugging */ alert("Enabled = " + document.queryCommandEnabled("copy") + " Design mode = " + document.designMode);

  try {
    document.execCommand('copy'); // Copy to clipbopard
  }
  catch (err) {
    alert('Unable to copy');
    console.log('Unable to copy'); // Copy failed?!
  }

  // document.designMode = 'off'; (Tried this, no effect)

  document.body.removeChild(sel); // Clean up removing the temporary holder
}

document.onkeydown=function(e){
  if(e.altKey && e.which == 49) { // Alt+1
    copy(link_variable);
    return false;
  }
}

有什么想法吗?

添加清单文件:

{
  "manifest_version": 2,
  "name": "Usage text",
  "version": "0.2",
  "description": "Whatever",
  "content_scripts": [
    {
      "matches": [
        "*://some.specific.site.com/*"
      ],
      "js": ["content.js"]
    }
  ],
  "background": {
    "scripts": ["background.js"]
  },
  "browser_action": {
      "name": "Whatever",
      "default_icon": "icon.png"
  },
  "permissions": [
    "tabs",
    "clipboardWrite"
  ]
}

更新:

将操作从content脚本转移到background脚本,没有变化。

【问题讨论】:

  • 您是否在清单中包含了clipboardWrite permission
  • 谢谢,不,我没有,但是现在按照您的评论尝试了,结果是一样的。添加了(更新的)清单文件。

标签: javascript google-chrome clipboard execcommand


【解决方案1】:

在尝试 Chromium 59 问题中的代码时记录了此警告:

[弃用] Selection.addRange() 合并现有 Range 和指定 Range 的行为已被删除。详情请见https://www.chromestatus.com/features/6680566019653632

那个

  1. 带我去上面提到的Chrome status

    在文档已经有文本选择并且调用了 Selection.addRange() 的情况下,如果 Range 和现有的文本选择有重叠,Blink 会将它们合并为一个,否则不执行任何操作。我们将对其进行更改,使 Blink 始终忽略 Range。它与 Edge 匹配。

    哪个

  2. 带我去discussion on that W3C specification

  3. 让我读了W3C specification

根据规范addRange() 如果已经有选择,则不应执行任何操作:

  1. 如果 rangeCount 不为 0,则中止这些步骤。

有趣的是,似乎已经有了选择。检查window. getSelection().rangeCount 确认了这一点。我无法解释为什么会这样,但这是问题中提到的问题的原因。

addRange() 之前调用removeAllRanges() 解决了这个问题:

var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);

【讨论】:

  • 再一次,我现在面临一个不同的问题 - addRange 命令选择文档的整个 HTML 代码,即自动生成的 HTML 文档以及临时 div 元素:@987654332 @ 这还包括紧跟在<script> 之后的<br class="Apple-interchange-newline">
  • 使用answer中的selectText函数解决了选择整个网页内容。谢谢,@try-catch-finally!
  • @try-catch-你终于是个天才了!在 addRange() 之前添加 removeAllRanges() 效果很好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-03
相关资源
最近更新 更多