如何在单击后以编程方式将异步依赖内容复制到剪贴板?

时间:2015-06-08 14:59:44

标签: javascript ajax clipboard zeroclipboard

我正在尝试以编程方式使用Chrome(Build 43)中的execCommand将异步JSONP请求的结果复制到剪贴板。这是逻辑的snippet

loadContent()

function loadContent(callback) {
  $.getJSON('http://www.randomtext.me/api/lorem/p-5/10-20?&callback=myFunc',function(result){
    console.log('result=',result.text_out);
    $("#container").html(result.text_out);
    if (callback) {
      callback();
    }
  });
}

function copyAjax() {

 loadContent(copy);

}

function copy() {
  var copyDivText = $('#container').text();
  console.log('copyDivText=',copyDivText);
  executeCopy(copyDivText);
}

document.addEventListener("DOMContentLoaded", function(){
      document.getElementById("copy").onclick = copy;
    });


document.addEventListener("DOMContentLoaded", function(){
      document.getElementById("copyAjax").onclick = copyAjax;
    });


// Copy text as text
function executeCopy(text) {
    var input = document.createElement('textarea');
    document.body.appendChild(input);
    input.value = text;
    input.focus();
    input.select();
    document.execCommand('Copy');
    input.remove();
}

我知道您开始构建43版本的Chrome使用execCommand和剪贴板。但问题是,您需要在执行用户发起的事件(其中权限被提升)中执行此操作。 这是ZeroClipboard基于闪存的解决方案所具有的类似限制。 除了得到一个不可能的答案(这是我现在正在思考的问题)之外,这些是我想做的其他选择(警告,它们都是Hail Mary Passes):

  1. 由于JSONP不能同步,因此将其转换为使用常规AJAX调用的内容,并确保AJAX调用在用户事件的执行上下文中是同步的。这违背了我根深蒂固的信念,即我们不应该进行同步XHR调用,因为它会降低用户体验。
  2. 当用户使用鼠标接近复制按钮时,我们会抢先发送服务器请求,并希望在用户单击按钮之前足够快。这是一个明显的竞争条件,可能不是时间的一部分,当用户想要执行Ctrl / Command-C而不是单击复制按钮时,它将无法确定。
  3. 执行两个步骤。单击以触发呼叫,当内容可用时,显示内容可用的消息,然后再次单击消息区域以复制到剪贴板。它似乎不是最好的UX互动。我已经使用此替代方法创建了this example。以编程方式触发单击不会构成用户问题事件。
  4. 可能有一种方法可以创建简单的Chrome扩展程序,并允许用户将该扩展程序的权限设置为复制到剪贴板。这涉及但最终用户必须安装和扩展并更改本地浏览器设置。不确定很多用户是否有能力/愿意这样做。
  5. 我已经研究过诸如this之类的Stackoverflow问题,但它们没有解决异步情况。 如果您能找到任何其他可行的解决方案(或对现有解决方案进行调整),请告诉我。

1 个答案:

答案 0 :(得分:6)

这是基于您的代码段的工作超时方法:

HTML:

<div id="container">
Enter Text To Copy</br>
<textarea id="clipboard"></textarea>
</div>
<input type="button" value="Copy" id="copy"/>

JS:

var timeout = 600; // timeout based on ajax response time
var loaded = false;

function loadContent() {
  loaded = false;
  $.getJSON('http://codepen.io/gkohen/pen/QbvoQW.js',function(result){
    document.getElementById("clipboard").value = result.lorem;
    loaded = true;
  });
}

// Copy text as text
function copy() {
  clipboard = document.getElementById("clipboard");
  if (!loaded || clipboard.value.length == 0) {
    alert("Ajax timeout! TIP: Try to increase timeout value.");
    return;
  }

  clipboard.focus();
  clipboard.select();

  if (document.execCommand('Copy'))
    alert("Successfuly coppied to clipboard!");

  // set defaults
  clipboard.value = "";
  loaded = false;
}

document.addEventListener("DOMContentLoaded", function(){
  document.getElementById("copy").onmousedown = loadContent;
  document.getElementById("copy").onclick = function() {
    setTimeout(copy, timeout); // wait for ajax
  }
});

主要问题是execCommand规范。有关安全性和trusted操作的一些限制。所以你必须制作事件调用副本和ajax调用公寓。这可以通过可破坏的睡眠以脏方式 - 通过固定超时(上面的代码)或正确的方式完成。提到了新的睡眠功能here,也许可以通过clearTimeout修改为可破坏的变体,但我没有尝试。