很酷吧,相信经常在网上复制粘贴的人应该不陌生,我也是经历过,觉得很神奇,所以就寻思着是不是也在自己的博客里面也实现这个功能,经过一番查资料于研究,我总算弄明白了其中的原委,并实际应用于我的博客,你可以复制我粘贴试试,觉得酷的话就可以往下接着看了!下面来看一下实现过程。这里说明一下,浏览器版本较低的话可能`addEventListener()`不支持,特别是IE浏览器,IE8以前包括IE8的版本都不支持此方法。
当用户选中某段内容时windowgetSelection()获取一个Selection对象,将这个`objSelectiontostring()`,就是选中区的内容,这里可以用` var selectionString = windowgetSelection()toString()`在控制台查看,能在控制台查看说明我们就可以通过js获取到,selectionString + '自定义内容',到这里复制的原内容我们就有了。这里我们要创建一个DOM容器来存`objSelectiontostring()`,最好是可以换行的,如p、div、textarea等。
当一个HTML文档切换到设计模式时,document暴露 execCommand 方法,该方法允许运行命令来 *** 纵可编辑内容区域的元素,这里主要用其中的copy命令来实现复制功能,听说插件Clipboardjs也是调用这个方法实现复制功能的`bool = documentexecCommand(aCommandName, aShowDefaultUI, aValueArgument)`,第一个参数是命令的名称,字符串类型,后两个参数我们可以不用,返回bool值,如果是 false则表示 *** 作不被支持或未被启用命令只介绍用到的copy命令:
> copy:拷贝当前选中内容到剪贴板。启用这个功能的条件因浏览器不同而不同,而且不同时期,其启用条件也不尽相同。使用之前请检查浏览器兼容表,以确定是否可用。
这是很重要的一步,这是复制内容的关键命令。这里我们只需要在正确的时间执行`documentexecCommand('copy')`即可。
addEventListener()方法用于向指定元素添加事件句柄,这里我就抛开文档,就针对本次功能对这个HTML DOM方法进行通俗的解释了,这里主要用来规定我们自定义复制功能的有效DOM范围,来个例子:
//body中有<div id="test">content</div>
var el = documentgetElementById('test');
eladdEventListener('copy', function (e){
// 触发copy事件后的处理
}
这个例子中我们实现的功能将只在id为test的DOM元素里有效,其它地方将恢复默认复制功能。
Range表示包含节点和部分文本节点的文档片段。用`var range = documentcreateRange()`方法创建,这里面为什么要创建Range呢,主要是用来存储Selection对象的开始位置和终点位置,因为我们是要阻止默认的copy事件,让copy的内容是用户选中的内容加上我们自定义的内容,再将这个内容放入粘贴板,形成最终的粘贴内容。`documentcreateRange`得到是还没有放内容的片段,我们我们还会用到`RangesetStart()`设置Range的起点和`RangesetEnd()`设置Range的终点。最终`selectionObjremoveAllRanges()`将selectionObj中的默认Range 去掉,`selectionObjaddRange(range)`,粘贴板就有了,不出意外去粘贴就会有选中的内容加自定义的内容了。
源码可以联系作者。这里有个特别注意的点,如果是原生js的话直接调用函数就可以,如果是vuejs的话中可以看到,我是在mounted()钩子函数里调用,而不是在created()钩子函数里调用,这里一定不能在created()钩子函数里调用,为什么呢?
因为created()执行的时候一般是在html渲染前的 *** 作,此时el还是undefined,所以执行getElementById()就会报错,created()适合做html渲染前的数据初始化工作。而mounted()一般是在html渲染完成后的 *** 作,此时el,data都已经加载完成,一般对dom的 *** 作都写在mounted中,这是个要注意的点,喜欢的话就给作者点个心,谢谢
原理分析
提取 *** 作:复制=>粘贴=>上传
在这个 *** 作过程中,我们需要做的就是:监听粘贴事件=>获取剪贴板里的内容=>发请求上传
为方便理解下文,需要先明白几点:
我们只能上传网页图(在网页上右键,然后复制)和截图(截图工具截的,eg:qq截图),不能粘贴上传系统里的(从桌面上、硬盘里复制),他们是存在完全不同的地方的。 截图工具截的图与在网页点击右键复制的图是有些不同的,因此处理方式也不一样。 知悉paste event这个事件:当进行粘贴(右键paste/ctrl+v) *** 作时,该动作将触发名为'paste'的剪贴板事件,这个事件的触发是在剪贴板里的数据插入到目标元素之前。如果目标元素(光标所在位置)是可编辑的元素(eg:设置了contenteditable属性的div。textarea并不行。),粘贴动作将把剪贴板里的数据,以最合适的格式,插入到目标元素里;如果目标元素不可编辑,则不会插入数据,但依然触发paste event。数据在粘贴的过程中是只读的。此段是翻译于w3org_the-paste-action。 可惜的是,经过试验,发现chrome(当前最新版)、firefox(当前最新版)、ie11对paste事件的实现并不是完全按照w3c来的,各自也有区别(w3c的paste标准也因此只是草案阶段)。
test代码如下:
chrome:
<textarea ></textarea> <div contenteditable style="width: 100px;height: 100px; border:1px solid"> </div> <script> documentaddEventListener('paste', function (event) { consolelog(event) }) </script>
event有clipboardData属性,且clipboardData有item属性,clipboardDataitem中的元素(对象)有type和kind属性; 无论在哪进行粘贴,均可触发paste事件; 在div(未特殊声明时,本文div均指设置了contenteditable属性的div) 里粘贴截图,不显示。imgsrc为base64编码字符串; 在div里粘贴网页,直接显示,imgsrc为地址。
firefox:
event有clipboardData属性,clipboardData没有item属性; 只有在textarea里或者可编辑的div(里才粘贴才触发paste事件; 在div里粘贴截图,直接显示,imgsrc为base64编码字符串; 在div里粘贴网页,表现同chrome。
ie11:(不截图了,可自行试验,其他浏览器同理<( ̄▽ ̄)/,因为懒)
event没有clipboardData属性; 只在可编辑的div中粘贴才触发paste事件; 在div里粘贴截图,直接显示,imgsrc为base64编码字符串; 在div里粘贴网页,表现同chrome。
监听了paste事件,也知道了表现形式,接下来就是如何获取数据了:
chrome有特定的方法,利用clipboardDataitems、getAsFile()、new FileReader()等api可以在paste回调函数里获取到剪贴板里的base64编码字符串(无论是截图粘贴的还是网页复制粘贴的),ie11,firefox没有这样的api,不过依然有办法可以获取,因为数据已经表现在img的src里了,对于截图粘贴的,直接取img的src属性值(base64),对于网页粘贴的,则把地址传给后台,然后根据地址down下来,存在自己的服务器,最后把新地址返回来交给前端展示就ok了。为了保持一致性便于管理,统一将所有情况(截图、网页)中的img的src属性替换为自己存储的地址。因此可以得到以下核心代码(注释很全哦~~):
html展示:
<head> <meta charset="UTF-8"> <title>Document</title> <style> body { display: -webkit-flex; display: flex; -webkit-justify-content: center; justify-content: center; } #tar_box { width: 500px; height: 500px; border: 1px solid red; } </style>
前端js处理逻辑:
documentaddEventListener('paste', function (event) { consolelog(event) var isChrome = false; if ( eventclipboardData || eventoriginalEvent ) { //not for ie11 某些chrome版本使用的是eventoriginalEvent var clipboardData = (eventclipboardData || eventoriginalEventclipboardData); if ( clipboardDataitems ) { // for chrome var items = clipboardDataitems, len = itemslength, blob = null; isChrome = true; //itemslength比较有意思,初步判断是根据mime类型来的,即有几种mime类型,长度就是几(待验证) //如果粘贴纯文本,那么len=1,如果粘贴网页,len=2, items[0]type = 'text/plain', items[1]type = 'image/' //如果使用截图工具粘贴,len=1, items[0]type = 'image/png' //如果粘贴纯文本+HTML,len=2, items[0]type = 'text/plain', items[1]type = 'text/html' // consolelog('len:' + len); // consolelog(items[0]); // consolelog(items[1]); // consolelog( 'items[0] kind:', items[0]kind ); // consolelog( 'items[0] MIME type:', items[0]type ); // consolelog( 'items[1] kind:', items[1]kind ); // consolelog( 'items[1] MIME type:', items[1]type ); //阻止默认行为即不让剪贴板内容在div中显示出来 eventpreventDefault(); //在items里找粘贴的image,据上面分析,需要循环 for (var i = 0; i < len; i++) { if (items[i]typeindexOf("image") !== -1) { // consolelog(items[i]); // consolelog( typeof (items[i])); //getAsFile() 此方法只是living standard firefox ie11 并不支持 blob = items[i]getAsFile(); } } if ( blob !== null ) { var reader = new FileReader(); readeronload = function (event) { // eventtargetresult 即为的Base64编码字符串 var base64_str = eventtargetresult //可以在这里写上传逻辑 直接将base64编码的字符串上传(可以尝试传入blob对象,看看后台程序能否解析) uploadImgFromPaste(base64_str, 'paste', isChrome); } readerreadAsDataURL(blob); } } else { //for firefox setTimeout(function () { //设置setTimeout的原因是为了保证先插入到div里,然后去获取值 var imgList = documentquerySelectorAll('#tar_box img'), len = imgListlength, src_str = '', i; for ( i = 0; i < len; i ++ ) { if ( imgList[i]className !== 'my_img' ) { //如果是截图那么src_str就是base64 如果是复制的其他网页那么src_str就是此在别人服务器的地址 src_str = imgList[i]src; } } uploadImgFromPaste(src_str, 'paste', isChrome); }, 1); } } else { //for ie11 setTimeout(function () { var imgList = documentquerySelectorAll('#tar_box img'), len = imgListlength, src_str = '', i; for ( i = 0; i < len; i ++ ) { if ( imgList[i]className !== 'my_img' ) { src_str = imgList[i]src; } } uploadImgFromPaste(src_str, 'paste', isChrome); }, 1); } }) function uploadImgFromPaste (file, type, isChrome) { var formData = new FormData(); formDataappend('image', file); formDataappend('submission-type', type); var xhr = new XML>
<input type="text" id="copyText" value="" style="color:#fff; background:#fff; border-color:#fff;border: 0; position:absolute; top:-50px; left:0;" />
<script type="text/jscript">
//复制文本
function copyText(str)
{
if(strlength >0)
{
$("#copyText")val(str);
//复制文本
var input = documentgetElementById("copyText");
inputvalue = str; // 修改文本框的内容
inputselect(); // 选中文本
documentexecCommand("copy"); // 执行浏览器复制命令
//layer提示框
layercloseAll('msg',{time:10000});
layermsg('<span style="color:red;">已复制:</span></br>'+str);
}
}
</script>
<a href="jscript:copyText('要复制的内容')">要复制的内容</a>
这是代码,这里的文本框不能设置隐藏,否则复制失效,所以我设置的样式让它在浏览器之外的地方,无法被看到
复制到剪贴板:windowclipboardDatasetData("Text",值的变量)
从剪贴板读取:windowclipboardDatagetData("Text")
放文字试过,方没试过。
不过可以给你参考一下js~,你自己试试,成功了可以告诉我。
script
function copyToClipboard()
{
var d = documentall("source")value;
windowclipboardDatasetData('text', d);
}
/script
BODY
button onclick="copyToClipboard();"拷贝/button
input type="text" size=20 id="source" value="测试数据"
br
button onclick="alert(windowclipboardDatagetData('text'));"显示/button
button onclick="windowclipboardDataclearData('text');"清空/button
/BODY
<script language="javascript">
var G=documentgetElementById;
function window_load(){
var str = "Test String";
//将字串放进剪贴板,执行完这个html页面后,你可以打开一个文本文件,按ctr+v看看
clipboardDatasetData("text",str);
//从剪贴板取值的方法,
//clipboardDatagetData("text");
//清空剪贴板的方法
//clipboardDataclearData();
}
</script>
javascript代码
<SCRIPT LANGUAGE="JavaScript">
function copyText(text)
{
windowclipboardDatasetData("text",text);
}
</SCRIPT>
HTML代码
<body onload=copyText('123')>
</body>
以上就是关于js实现网页内自定义粘贴板全部的内容,包括:js实现网页内自定义粘贴板、js怎么实现将截图,或者复制的图片用ctrl+v、js将内容放到剪贴板怎么写呢等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)