这是我的网站的一个新特性——“复制”按钮。

Clip_2024-06-20_18-34-09

它使我的读者使用我的网站时会更加流畅、更加便利,网站可视化效果改善,进而读者的心情就会更好,然后就会给我评论

现在我们来说说这是如何实现的。


插件

我发现了 clipboard.js 这样一款插件。

网站内容十分简洁,教会了我们这样一些东西:

  • CDN 引用:

    <script src="https://cdn.bootcdn.net/ajax/libs/clipboard.js/2.0.11/clipboard.min.js"></script>
    
  • 对于 btn 类下的元素,我们可以利用 JS 这样调用 clipboardjs:

    new ClipboardJS('.btn');
    
  • 根据网站给出的 DEMO,我们可以自行设计程序。

Clip_2024-06-20_18-39-06

于是,我们就有了雏形:

recording

问题

如果要把它直接利用到网站里面,就出现了问题。

观察刚才的程序可以知道,每个 <button> 和每个 <pre> 是以后者唯一确定的 id 联系起来的。如果出现多个代码块,就需要多个不同的 id 以及不同的按钮,并将它们一一对应起来。而且由于 Gridea 并未设置代码块的 id,所以就需要手动分配了。

这显然需要用到 JS 了。思考一番后,我写出了如下的 JS 程序:

document.addEventListener('DOMContentLoaded', () => {
    const pres = document.querySelectorAll('pre');
    pres.forEach((pre, index) => {
        // 创建唯一确定的的 id
        const uniqueId = `pre-${index + 1}`;
        pre.id = uniqueId;
        // 创建按钮
        const button = document.createElement('button');
        button.className = 'btn';
        button.innerText = 'Copy';
        // 设置 data-clipboard-target 属性
        button.setAttribute('data-clipboard-target', `#${uniqueId}`);
        // 在 pre 标签之前插入按钮
        pre.parentNode.insertBefore(button, pre);
	});
});

把它放到刚才雏形的最后:

Clip_2024-06-20_19-02-49
recording

问题解决。把上面的解决方案放在 footer.ejs 中即可。

美化

刚才的普通按钮太丑了。添加一些 CSS 对它美化,请把它放在 main.less 中:

/* main.less */
.btn {
    padding: 5px 10px;
    margin-bottom: 10px;
    background-color: #007BFF;
    color: white;
    border: none;
    border-radius: 5px;
    cursor: pointer;
}
Clip_2024-06-20_19-05-29

再来,引用 Font Awesome,添加一个图标:

<!-- head.ejs -->
<link rel="stylesheet" href="https://cdn.staticfile.org/font-awesome/4.7.0/css/font-awesome.css">
<!-- footer.ejs -->
<script>
document.addEventListener('DOMContentLoaded', () => {
    const pres = document.querySelectorAll('pre');
    pres.forEach((pre, index) => {
        // 创建唯一确定的的 id
        const uniqueId = `pre-${index + 1}`;
        pre.id = uniqueId;
        // 创建按钮
        const button = document.createElement('button');
        button.className = 'btn';
        button.innerHTML = '<span>Copy</span> <span class="fa fa-copy"></span>';
        // 设置 data-clipboard-target 属性
        button.setAttribute('data-clipboard-target', `#${uniqueId}`);
        // 在 pre 标签之前插入按钮
        pre.parentNode.insertBefore(button, pre);
	});
});
</script>
Clip_2024-06-20_19-10-42

可以,最终目的达到了。

现在把它放在 Gridea 里面试试,就有了最开始的那个样子。

完结撒花!~