单击后如何以编程方式将异步相关内容复制到剪贴板?
How to programmatically copy asynchronous dependent content to the clipboard following a click?
我正在尝试以编程方式使用 Chrome(内部版本 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 of Chrome 你的代码使用带剪贴板的 execCommand。然而,问题是您需要在执行用户发起的事件(其中提升权限)时执行此操作。
这与 ZeroClipboard 基于闪存的解决方案具有类似的限制。
除了得到一个不可能的答案(这是我现在正在思考的),这些是我认为作为最后手段的其他选择(警告,它们都是 Hail Mary Passes):
- 由于 JSONP 不能同步,将其转换为使用常规 AJAX 调用的东西,并确保 AJAX 调用在用户事件的执行上下文中是同步的。这违背了我根深蒂固的信念,我们不应该进行同步 XHR 调用,因为它会降低用户体验。
- 当用户用鼠标接近复制按钮时,我们先发制人地发送服务器请求并希望在用户单击按钮之前速度足够快。这是一个明显的竞争条件,可能不是部分时间,并且当用户想要执行 Ctrl/Command-C 而不是单击复制按钮时肯定不会工作。
- 执行两步过程。单击一次触发呼叫,当内容可用时,显示内容可用的消息,然后再次单击消息区域以复制到剪贴板。它看起来不像是有史以来最好的 UX 交互。我用这个 alternative.Triggering 创建了 this example 以编程方式点击不构成用户问题事件。
- 可能有一种方法可以创建一个简单的 Chrome 扩展,并让用户为该扩展设置复制到剪贴板的权限。这涉及到最终用户必须安装和扩展以及更改本地浏览器设置。不确定很多用户会 capable/willing 这样做。
我已经研究过诸如 this 之类的 Whosebug 问题,但它们并未解决异步场景。
如果您能找到任何其他可行的解决方案(或对现有解决方案进行调整),请告诉我。
这是基于您的代码段的工作超时方法:
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 actions. So you have to make event calling copy and ajax call aparte. This can be done dirty way - by fixed timeout (code above) or proper way - by breakable sleep. New sleep feature is mentioned here 有一些限制,也许可以通过 clearTimeout 修改为可破坏的变体,但我没有尝试。
我正在尝试以编程方式使用 Chrome(内部版本 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 of Chrome 你的代码使用带剪贴板的 execCommand。然而,问题是您需要在执行用户发起的事件(其中提升权限)时执行此操作。 这与 ZeroClipboard 基于闪存的解决方案具有类似的限制。 除了得到一个不可能的答案(这是我现在正在思考的),这些是我认为作为最后手段的其他选择(警告,它们都是 Hail Mary Passes):
- 由于 JSONP 不能同步,将其转换为使用常规 AJAX 调用的东西,并确保 AJAX 调用在用户事件的执行上下文中是同步的。这违背了我根深蒂固的信念,我们不应该进行同步 XHR 调用,因为它会降低用户体验。
- 当用户用鼠标接近复制按钮时,我们先发制人地发送服务器请求并希望在用户单击按钮之前速度足够快。这是一个明显的竞争条件,可能不是部分时间,并且当用户想要执行 Ctrl/Command-C 而不是单击复制按钮时肯定不会工作。
- 执行两步过程。单击一次触发呼叫,当内容可用时,显示内容可用的消息,然后再次单击消息区域以复制到剪贴板。它看起来不像是有史以来最好的 UX 交互。我用这个 alternative.Triggering 创建了 this example 以编程方式点击不构成用户问题事件。
- 可能有一种方法可以创建一个简单的 Chrome 扩展,并让用户为该扩展设置复制到剪贴板的权限。这涉及到最终用户必须安装和扩展以及更改本地浏览器设置。不确定很多用户会 capable/willing 这样做。
我已经研究过诸如 this 之类的 Whosebug 问题,但它们并未解决异步场景。 如果您能找到任何其他可行的解决方案(或对现有解决方案进行调整),请告诉我。
这是基于您的代码段的工作超时方法:
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 actions. So you have to make event calling copy and ajax call aparte. This can be done dirty way - by fixed timeout (code above) or proper way - by breakable sleep. New sleep feature is mentioned here 有一些限制,也许可以通过 clearTimeout 修改为可破坏的变体,但我没有尝试。