如何制作一个获取外部资源并将其复制到剪贴板的按钮?
How do I make a button that gets an external resource AND copies it to the clipboard?
所以我有一个按钮,可以制作精美的分享 URL,使用 goo.gl 缩短它,然后将其复制到剪贴板。好消息是,我已经成功完成了所有这些,但不是一次完成。
问题源于规范:
Copy commands triggered from document.execCommand() will only affect the contents of the real clipboard if the event is dispatched from an event that is trusted and triggered by the user, or if the implementation is configured to allow this. How implementations can be configured to allow write access to the clipboard is outside the scope of this specification.
execCommand Unofficial W3C Spec
看来这可能行不通...
你看,为了缩短 URL,我需要打一个 AJAX 电话。我只在用户点击分享按钮时才这样做,因为我每天有 1,000,000 次缩短的限制(如果每次页面更改时我都生成一个新的分享 URL,那很容易是 1,000 个新的 URLs 对于一个用户,所以我将被限制为最多 1,000 个最终用户:不是最佳选择)。但这意味着我必须从发起事件的线程以外的线程监听 AJAX 事件,实际上失去了 execCommand('copy')
.
所需的这种祝福状态
有没有办法让一个按钮同时生成 goo.gl URL 和 then 复制说短 URL 到剪贴板?
供参考,here's what I wrote (Kotlin/JS) and here's the JavaScript output。
这里是 a SSCCE that illustrates how it seems like it should work, but does not (based on 陈杨华's answer).
有 2 个解决方案有效,但都存在缺陷。一种仅在您的请求少于一秒时有效,另一种已弃用,因此不应在生产环境中使用。
第一个是使用 setTimeout,这是少数几个不丢失 execCommand "privilege".但它不会丢失等于或小于 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);
});
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);
});
所以我有一个按钮,可以制作精美的分享 URL,使用 goo.gl 缩短它,然后将其复制到剪贴板。好消息是,我已经成功完成了所有这些,但不是一次完成。
问题源于规范:
Copy commands triggered from document.execCommand() will only affect the contents of the real clipboard if the event is dispatched from an event that is trusted and triggered by the user, or if the implementation is configured to allow this. How implementations can be configured to allow write access to the clipboard is outside the scope of this specification.
execCommand Unofficial W3C Spec
看来这可能行不通...
你看,为了缩短 URL,我需要打一个 AJAX 电话。我只在用户点击分享按钮时才这样做,因为我每天有 1,000,000 次缩短的限制(如果每次页面更改时我都生成一个新的分享 URL,那很容易是 1,000 个新的 URLs 对于一个用户,所以我将被限制为最多 1,000 个最终用户:不是最佳选择)。但这意味着我必须从发起事件的线程以外的线程监听 AJAX 事件,实际上失去了 execCommand('copy')
.
有没有办法让一个按钮同时生成 goo.gl URL 和 then 复制说短 URL 到剪贴板?
供参考,here's what I wrote (Kotlin/JS) and here's the JavaScript output。
这里是 a SSCCE that illustrates how it seems like it should work, but does not (based on 陈杨华's answer).
有 2 个解决方案有效,但都存在缺陷。一种仅在您的请求少于一秒时有效,另一种已弃用,因此不应在生产环境中使用。
第一个是使用 setTimeout,这是少数几个不丢失 execCommand "privilege".但它不会丢失等于或小于 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);
});
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);
});