Jаvascript
为代码块添加一个"复制代码"按钮,并实现点击按钮后将代码块的内容复制到剪贴板中。
- 首先通过
document.querySelectorAll('pre')
获取所有<pre>
元素(即代码块)。- 使用
forEach
方法遍历每个代码块。- 创建一个文本元素
copyButton
,设置其class为"copy",并将显示文本设置为"复制代码"。- 创建一个容器元素
container
,设置其class为"code-container",并将复制按钮添加到容器元素内。- 将容器元素插入到代码块之前。
- 设置容器元素样式,使其定位为相对定位(position: relative)。
- 设置复制按钮样式,使其绝对定位于容器元素的右上角。
- 为复制按钮添加点击事件监听器。
- 在点击事件处理函数中,获取代码块的文本内容。
- if (navigator.clipboard && window.isSecureContext)以此判断使用不同的复制方法,使用navigator.clipboard.writeText(code).then(() => {}).catch(() => {});或采用document.execCommand('copy'); 这里需要借助创建textarea
- 创建一个临时的
<textarea>
元素,并将代码块的内容设置为其值。- 将
<textarea>
元素追加到<body>
中。- 选中
<textarea>
中的文本。- 执行复制操作,将选中的文本复制到剪贴板中。
- 移除临时的
<textarea>
元素。- 修改复制按钮文本为"复制成功"。
这段代码的作用是为网页中的代码块添加一个复制按钮,方便复制代码片段。
CSS
用于设置复制按钮和代码块的样式。具体样式如下:
.code-wrapper
类选择器用于设置包裹代码块的容器元素的样式。在这里设置了相对定位(position: relative)。.code-block
类选择器用于设置代码块的样式。在这里设置了相对定位(position: relative)。.copy
类选择器用于设置复制按钮的样式。具体样式如下:
font-size
:设置字体大小为 13px。transition
:设置颜色变化的过渡效果为 0.1秒。color
:设置按钮的颜色为带透明度的红色color: hsl(165.03deg 19.14% 92.37% / 97%);,背景为灰色background: #1b45bede;。border
:去掉按钮的边框。border-radius
:设置按钮的圆角为4px。cursor
:设置鼠标悬停在按钮上时的样式为指针。z-index
:将复制按钮的层级置于顶层,确保按钮显示在其他内容之上。
这些样式可以使用在前面提到的 jаvascript 脚本中的相关元素上,以实现更好的外观和交互效果。
js文件,直接在html中引用 ,如果是在vue中使用,需要在渲染html的方法中使用下面的js。
javascript
(function () {
"use strict"
// 获取<pre>元素
var codeBlocks = document.querySelectorAll('pre');
var codeContainer = document.querySelectorAll(".code-container");
if (codeBlocks && codeContainer.length === 0) {
codeBlocks.forEach(function (codeBlock) {
// 创建新的ol元素
// const ol = document.createElement('ol');
// // 获取所有<code>标签中的文本行
// const codeLines = codeBlock.textContent.split('\n');
// // 移除<pre>中的所有内容
// codeBlock.innerHTML = '';
// // 为每行代码添加序号并重新添加到<pre>中
// codeLines.forEach((line, index) => {
// const lineNumber = index + 1;
// const lineElement = document.createElement('li');
// lineElement.textContent = `${line}`;//${lineNumber}.
// ol.appendChild(lineElement);
// // codeBlock.innerHTML = `<ol><li>${codeBlock.innerHTML.replace(/\n/g,`</li><li class="line">`)}</li></ol>`;
// });
// codeBlock.appendChild(ol);
var copyButton = document.createElement('span');
copyButton.className = 'copy';
copyButton.textContent = '复制代码';
// 创建包裹代码块和按钮的容器元素
var container = document.createElement('div');
container.className = 'code-container';
// 将按钮添加到容器元素内
container.appendChild(copyButton);
// 将容器元素插入到代码块之前
codeBlock.parentNode.insertBefore(container, codeBlock);
// 设置容器元素样式,使其定位为相对定位(position: relative)
container.style.position = 'relative';
// 设置复制按钮样式,使其绝对定位于容器元素的右上角
copyButton.style.position = 'absolute';
copyButton.style.top = '3px';
copyButton.style.right = '6px';
copyButton.addEventListener('click', function () {
// 获取代码块的文本内容textContent
var code = codeBlock.innerText;
if (navigator.clipboard && window.isSecureContext) {
try {
navigator.clipboard.writeText(code).then(() => {
// 修改复制按钮文本为"已复制"
this.textContent = '复制成功';
}).catch(() => {
this.textContent = '复制失败';
});
} catch (err) {
this.textContent = '复制失败';
}
} else {
// 创建一个临时的textarea元素,并将代码块的内容设置为其值
var textarea = document.createElement('textarea');
textarea.value = code;
// 将textarea元素追加到body中
document.body.appendChild(textarea);
// 选中textarea中的文本
textarea.select();
// 执行复制操作
document.execCommand('copy');
// 移除临时的textarea元素
document.body.removeChild(textarea);
this.textContent = '复制成功';
}
//一定时间后吧按钮名改回来
setTimeout(() => {
this.textContent = "复制代码";
}, 1800);
});
});
}
if (document.getElementById("copy-code-styles")) return; // 避免重复添加样式
const css = `
.code-wrapper {
position: relative;
}
.code-block {
position: relative;
}
.copy {
font-size: 13px;
transition: color 0.1s;
color: hsl(165.03deg 19.14% 92.37% / 97%);
background: #1b45bede;
padding: 0 3px;
border: none;
border-radius: 4px;
cursor: pointer;
z-index: 1;
}`;
const style = document.createElement("style");
style.id = "copy-code-styles";
style.textContent = css;
document.head.appendChild(style);
}());