js 实现代码模块粘贴复制功能
今天接受到需求,需要对之前做的代码高亮部分新增粘贴复制功能。
首先我们将复制按钮的dom结构与之前的pre code 的结构整合。
<div class="code-ct">
<div class="code-action">
<div class="switch-btn">
<i class="i-switch-1" title="明切暗"></i>
<i class="i-switch-2" title="暗切明"></i>
</div>
<div class="copy-btn">
<i class="i-copy" title="复制"></i>
<div class="i-copy-txt" style="display: none;">复制成功</div>
</div>
</div>
<pre>
<code>
代码内容XXX </code>
</pre>
</div>
复制功能代码实现js如下
r.on("click", ".i-copy", function(e) { var text = $(this).parents('.code-ct').children('pre').prevObject[0].innerText if (text.indexOf('复制成功') > 0) { // 处理IE 复制成功 text = text.replace('复制成功','') } var textarea = document.createElement('textarea') //textarea textarea.value = text // document.body.appendChild(textarea) // ie会有滚到底部bug $(this).parents('.code-ct').append($(textarea)) textarea.select(); // 选择对象 document.execCommand("Copy"); // 执行浏览器复制命令 textarea.className = 'copy-textarea' textarea.style.display='none' var a = parseInt($(this).data("timer")) || 0; var b = $(this).next(); b.show(), a && clearTimeout(a), a = setTimeout(function() { b.hide() $('.copy-textarea').remove() // 删除textarea }, 1e3), $(this).data("timer", a) })
总结注意几点
1 功能实现核心方法 document.execCommand("Copy"); // 执行浏览器复制命令
2 网上有些创建input标签 document.createElement('input') 这样会导致代码格式丢失
3 插入新建deom方式 document.body.appendChild(textarea) 经测试在ie上会自动滚动到底部
另还有弹框提示阻塞 textarea.style.display='none',通过样式影藏textarea标签。拷贝内容innerText含有标签内容,记得清除处理
4 创建后 将创建的临时dom删除 $('.copy-textarea').remove()
======= 上午高高兴兴提测后 下午bug就来了 说再苹果手机移动端无法复制 ========
解决方案 引入clipboard.js
<script src="/static/js/clipboard.js"></script>
添加影藏textarea
<textarea id="hide-texteare" v-show='false'></textarea>
对复制按钮绑定新属性data-clipboard-action的值是'copy '属性data-clipboard-target的值是textarea的id
<i class="i-copy" title="复制" data-clipboard-action="copy" data-clipboard-target="#hide-texteare"></i>
js代码
var clipboard = new ClipboardJS('.i-copy'); clipboard.on('success', function(e) { var a = parseInt($(e.trigger).data("timer")) || 0; var b = $(e.trigger).next(); b.show(), a && clearTimeout(a), a = setTimeout(function() { b.hide() }, 1e3), $(this).data("timer", a) e.clearSelection(); }); clipboard.on('error', function(e) { console.error('copy 失败'); });
测试后 主流浏览器及移动端均可实现复制功能
============= bug 又来了 在ie上测试 发现动态数据无法复制完全 ===========================
为了解决该问题。自己决定将上述两种方式做兼容处理
if (isIE()) { r.on("click", ".i-copy", function(e) { var text = $(this).parents('.code-ct').children('pre').prevObject[0].innerText if (text.indexOf('复制成功') > 0) { // 处理IE 复制成功 text = text.replace('复制成功','') } // console.log('IE text========', text) var textarea = document.createElement('textarea') //textarea textarea.value = text // document.body.appendChild(textarea) // ie会有滚到底部bug $(this).parents('.code-ct').append($(textarea)) textarea.select(); // 选择对象 document.execCommand("Copy"); // 执行浏览器复制命令 textarea.className = 'copy-textarea' textarea.style.display='none' var a = parseInt($(this).data("timer")) || 0; var b = $(this).next(); b.show(), a && clearTimeout(a), a = setTimeout(function() { b.hide() $('.copy-textarea').remove() // 删除textarea }, 1e3), $(this).data("timer", a) }) } else { // IE 使用ClipboardJS 动态数据复制不全 r.on("click", ".i-copy", function(e) { var text = $(this).parents('.code-ct').children('pre').prevObject[0].innerText $("#hide-texteare").text(text) // console.log('非 IE text========', text) }) var clipboard = new ClipboardJS('.i-copy'); clipboard.on('success', function(e) { var a = parseInt($(e.trigger).data("timer")) || 0; var b = $(e.trigger).next(); b.show(), a && clearTimeout(a), a = setTimeout(function() { b.hide() }, 1e3), $(this).data("timer", a) e.clearSelection(); }); clipboard.on('error', function(e) { console.error('copy 失败'); }); } function isIE() { if (!!window.ActiveXObject || "ActiveXObject" in window) return true; else return false; }
另外对修改了对clipboard.js全局引入方式,在webpack.base.conf.js中引入
resolve: { extensions: ['.js', '.vue', '.json'], alias: { 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src'), 'api': path.resolve(__dirname, '../src/assets/api/index.js'), 'assets': path.resolve(__dirname, '../src/assets'), 'static': path.resolve(__dirname, '../static'), 'ClipboardJS': 'clipboard/dist/clipboard.min.js' } },
plugins: [ new webpack.optimize.CommonsChunkPlugin('common.js'), new webpack.ProvidePlugin({ ClipboardJS: "ClipboardJS", }) ]