如何创建一个获取外部资源的按钮并将其复制到剪贴板?

Ben*_*ero 5 javascript clipboard dom-events goo.gl execcommand

所以我有一个按钮,它应该创建一个奇特的共享URL,使用goo.gl缩短它,然后将其复制到剪贴板.好消息是,我已经成功完成了所有这些,但并非一下子全部完成.

问题源于规范:

从document.execCommand()触发的复制命令只会影响真实剪贴板的内容,前提是从用户信任和触发的事件调度事件,或者实现配置为允许此事件.如何配置实现以允许对剪贴板的写访问超出了本规范的范围.

execCommand非官方W3C规范

所以看起来这可能不起作用......

你看,为了缩短URL,我需要进行一次AJAX调用.我只在用户点击分享按钮时才这样做,因为我每天有1,000,000个限制缩短(如果我每次更改页面时都生成一个新的共享URL,那么一个用户很容易就会有1,000个新的URL,所以我' d限制为最多1,000个最终用户:不是最佳选择).但这意味着我必须从发起事件的线程之外的线程中侦听AJAX事件,从而有效地失去了所需的这种祝福状态execCommand('copy').

有没有办法让一个单一的按钮同时生成goo.gl URL,然后将所说的短URL复制到剪贴板?

作为参考,这是我写的(Kotlin/JS)这里的JavaScript输出.
这是一个SSCCE,说明它应该如何工作,但不是(基于陈杨华的答案).

Jul*_*ire 3

有两种可行的解决方案,但都有缺陷。仅当您的请求花费的时间少于一秒时,其中一种才有效,并且一种已被弃用,因此不应在生产环境中使用。

第一个是使用setTimeout,它是少数不会失去execCommand “特权”的异步函数之一。但如果它等于或小于1000ms,它就不会丢失。因此,如果您的请求小于该值,则可以继续,但如果不是,则出现错误。如果将其与某种超时处理结合起来,它可以工作,但如果请求经常花费超过 1 秒,那么它可能不够好。例如这样:

var toCopy;

const buttonClick = () => {

  setTimeout(function() {
    if (toCopy) {
      // strangely, this execCommand will work
      console.log(document.execCommand('copy'));
    }
  }, 1000);

  var client = new XMLHttpRequest();
  client.onload = function(data) {

    toCopy = this.responseText;

  };

  // by setting your timeout on your request 
  // with the same duration as the setTiemout
  // you make sure it either works or throws an error
  client.ontimeout = function(data) {

    console.log('timeout');

  };
  client.timeout = 1000;
  client.open("GET", "https://www.random.org/integers/?num=1&min=1&max=100&col=1&base=10&format=plain");
  client.send();


}

$(() => {
  $("button").click(buttonClick)
})

document.addEventListener('copy', function(e) {

  e.preventDefault();
  e.clipboardData.setData('text/plain', toCopy);

});
Run Code Online (Sandbox Code Playgroud)

https://jsfiddle.net/8md4Ltu2/4/

还有另一种方法可以使其工作,但它已被弃用,因此不使用。但是,为了彻底起见,我将其放在这里。您可以将 XMLHttpRequest 的异步标志设置为 false。该请求将是同步的,并且 execCommand 的处理非常简单。但是这个同步标志已被弃用,指导原则是如果您尝试使用它会抛出错误,所以不要使用它。请参阅: https: //xhr.spec.whatwg.org/#synchronous-flag

var toCopy;

const buttonClick = () => {

  var client = new XMLHttpRequest();
  client.onload = function(data) {
    toCopy = this.responseText;
    console.log(document.execCommand('copy'));
  };


  client.open("GET", "https://www.random.org/integers/?num=1&min=1&max=100&col=1&base=10&format=plain", false);
  client.send();


}

$(() => {
  $("button").click(buttonClick)
})

document.addEventListener('copy', function(e) {

  e.preventDefault();
  e.clipboardData.setData('text/plain', toCopy);

});
Run Code Online (Sandbox Code Playgroud)

https://jsfiddle.net/zezskm2x/2/