Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何制作一个获取外部资源并将其复制到剪贴板的按钮?_Javascript_Clipboard_Dom Events_Execcommand_Goo.gl - Fatal编程技术网

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

Javascript 如何制作一个获取外部资源并将其复制到剪贴板的按钮?,javascript,clipboard,dom-events,execcommand,goo.gl,Javascript,Clipboard,Dom Events,Execcommand,Goo.gl,所以我有一个按钮,用来创建一个奇特的共享URL,使用goo.gl将其缩短,然后将其复制到剪贴板。好消息是,我已经成功地完成了所有这些,但不是一下子完成的 问题源于规范: 从document.execCommand()触发的复制命令只会影响真实剪贴板的内容,如果事件是从用户信任并触发的事件中发送的,或者如果实现配置为允许这样做。如何配置实现以允许对剪贴板进行写访问超出了本规范的范围 所以看起来这可能不起作用 你看,为了缩短URL,我需要做一个AJAX调用。我只在用户单击共享按钮时才这样做,因为我

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

问题源于规范:

从document.execCommand()触发的复制命令只会影响真实剪贴板的内容,如果事件是从用户信任并触发的事件中发送的,或者如果实现配置为允许这样做。如何配置实现以允许对剪贴板进行写访问超出了本规范的范围

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

你看,为了缩短URL,我需要做一个AJAX调用。我只在用户单击共享按钮时才这样做,因为我每天的缩短次数限制为1000000次(如果每次页面更改时我都生成一个新的共享URL,那么一个用户很容易会有1000个新URL,因此我最多只能有1000个最终用户:这不是最好的选择)。但这意味着我必须从一个线程(而不是发起事件的线程)侦听AJAX事件,实际上会丢失
execCommand('copy')
所需的这种良好状态

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

供参考,及

以下是(基于)。

有两种解决方案可行,但都有缺陷。只有当您的请求占用的时间少于一秒钟时,一个才有效,另一个已弃用,因此不应在生产环境中使用

第一种方法是使用setTimeout,这是不丢失execCommand特权的少数异步函数之一。但当它等于或小于1000毫秒时,它不会丢失。因此,如果您的请求小于此值,您可以继续,但如果没有,则您有一个错误。如果将它与某种超时处理结合起来,它可以工作,但是如果请求通常需要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);

});

还有另一种方法可以使它工作,但它已被弃用,因此不能使用。但是,为了彻底起见,我会把它放在这里。您可以将XMLHttpRequest的异步标志设置为false。请求将是同步的,并且execCommand的处理非常简单。但此同步标志已被弃用,准则是在尝试使用它时抛出错误,因此不使用它。见:


。你试过用承诺吗?@osa没有!你能给出一个例子的答案吗?@osa既然你没有回应,我就把赏金给你。尽管如此,请随时发布您的解决方案,我会公平对待!setTimeout只有在1000毫秒或以下时才有效,ajax调用可能需要更多时间。(关于chrome,时间限制是特定于浏览器的)@munimunna你说得对,我不知道也没有尝试过。我将编辑我的答案这些答案不是相互排斥的,所以我将尝试实现它们。它们结合在一起,似乎形成了一个跨浏览器的解决方案!我会在将来的某一天记下重新讨论这个问题,但它现在起作用:)
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);

});