今天在 OJ 网站上增加了拷贝功能。开始的时候使用的是 JavaScript 原生的功能。对应的 JavaScript 代码如下:
function copyDivToClipboard(containerid) {
if (window.getSelection) {
if (window.getSelection().empty) {
// Chrome
window.getSelection().empty();
} else if (window.getSelection().removeAllRanges) {
// Firefox
window.getSelection().removeAllRanges();
}
} else if (document.selection) {
// IE?
document.selection.empty();
}
if (document.selection) {
var range = document.body.createTextRange();
range.moveToElementText(document.getElementById(containerid));
range.select().createTextRange();
document.execCommand("copy");
alert("拷贝成功");
} else if (window.getSelection) {
var range = document.createRange();
range.selectNode(document.getElementById(containerid));
window.getSelection().removeAllRanges(); // clear current selection
window.getSelection().addRange(range); // to select text
document.execCommand("copy");
window.getSelection().removeAllRanges();// to deselect
alert("拷贝成功");
}
}
由于需要提醒拷贝成功,只能使用 alert 来弹窗。当然这样用户体验肯定很差。
然后在网络上看到了一个开源的 ClipboardJS,功能非常强大。按照官网的介绍,使用很非常简单。
官网为 https://github.com/zenorocha/clipboard.js。
我使用第三方 CDN 的网址。
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/clipboard.min.js"></script>
<script>
new ClipboardJS('.btn');
</script>
对应的 HTML 脚本为
<input id="foo" value="https://github.com/zenorocha/clipboard.js.git" />
<button class="btn" data-clipboard-target="#foo">
<img src="assets/clippy.svg" alt="Copy to clipboard" />
button>
<textarea id="bar">Mussum ipsum cacilds...textarea>
<button class="btn" data-clipboard-action="cut" data-clipboard-target="#bar">
Cut to clipboard
button>
<button
class="btn"
data-clipboard-text="Just because you can doesn't mean you should — clipboard.js"
>
Copy to clipboard
button>
从上面的脚本中可以看到,我们只需要将需要支持拷贝功能,只需要将 class 设置为 btn,配合 JavaScript 的脚本(具体参考上面的 JavaScript)。
<html lang="fr" class="h-100">
<head>
<meta charset="utf-8">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/clipboard.min.js">script>
<script>
// Clipboard
var clipboard = new ClipboardJS('.btn');
script>
head>
<body>
<br>
<input id="foo" value="https://github.com/zenorocha/clipboard.js.git" />
<button class="btn" data-clipboard-target="#foo">
<img src="assets/clippy.svg" alt="Copy to clipboard" />
button>
<br>
<textarea id="bar">Mussum ipsum cacilds...textarea>
<button class="btn" data-clipboard-action="cut" data-clipboard-target="#bar">
Cut to clipboard
button>
<br>
<button
class="btn"
data-clipboard-text="Just because you can doesn't mean you should — clipboard.js"
>
Copy to clipboard
button>
body>
html>
神奇的事情发生了,ClipboardJS 没有任何作用。经过 n+1 小时的苦苦调试,发现
var clipboard = new ClipboardJS('.btn');
这里奔溃了。惭愧 JS 只是会用,不懂。面对这个问题百思不得其解。
后面可能是灵光一动。原文件是在 中调用 JS 脚本,尝试将创建对象的脚本放置到 段中。
然后申请的事情就发生了,clipboard 对象可以成功产生。
也就是说,我们必须将上面的 JS 脚本放在 段中。天坑啊。
ClipboardJS 本生是不提供 tooltip 功能的。按照官网的说法:
Each application has different design needs, that’s why clipboard.js does not include any CSS or built-in tooltip solution.
The tooltips you see on the demo site were built using GitHub’s Primer. You may want to check that out if you’re looking for a similar look and feel.
也就是说需要自己配合 CSS 来实现这个功能。后面经过 google,发现了一段代码,使用 clipboard + jquery + bootstrap 来实现,挺好用的。
<html lang="fr" class="h-100">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js">script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js">script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js">script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/clipboard.min.js">script>
head>
<body>
<script>
// Tooltip
$('#copy').tooltip({
trigger: 'click',
placement: 'bottom'
});
function setTooltip(message) {
$('#copy').tooltip('hide')
.attr('data-original-title', message)
.tooltip('show');
}
function hideTooltip() {
setTimeout(function() {
$('#copy').tooltip('hide');
}, 1000);
}
// Clipboard
var clipboard = new ClipboardJS('.btn');
clipboard.on('success', function(e) {
setTooltip('Copied!');
hideTooltip();
});
clipboard.on('error', function(e) {
setTooltip('Failed!');
hideTooltip();
});
script>
<br>
<br>
<br>
<div class="row justify-content-center mt-5">
<button id="copy" class="btn btn-primary" data-clipboard-text="hi">
Copy to clipboard
button>
div>
body>
html>
上面的文件在 Chrome、Firefox、Edge 上都测试过。运行的效果如下:
讲真,挺不错的。就是 ClipboardJS 这个 BUG 然人哭笑不得,白浪费了半天。