原生JavaScript实现复制/粘贴

摘要

在IE7及其以下版本浏览器中,由于不具备直接访问剪贴板的能力,开发者只能借助于flash插件来实现这一功能。而现在不部分现在浏览器支持剪贴板功能,Mac和iOS上的Safari除外。但是不同浏览器的支持程度不尽相同,而且一些功能并不完整或存在缺陷,需要考虑的兼容性问题较多。用户必须通过点击鼠标或按键的方式来主动触发,脚本并不能随时操纵剪贴板。

IE7及其以下版本浏览器中,由于不具备直接访问剪贴板的能力,开发者只能借助于flash插件来实现这一功能。

而现在不部分现在浏览器支持剪贴板功能,Mac和iOS上的Safari除外。但是不同浏览器的支持程度不尽相同,而且一些功能并不完整或存在缺陷,需要考虑的兼容性问题较多。用户必须通过点击鼠标或按键的方式来主动触发,脚本并不能随时操纵剪贴板。

下面总结一下剪贴板的JavaScript语法。

一. 剪贴板事件

  • beforecopy:在发生复制操作前触发;
  • copy:在发生复制操作的时候触发;
  • beforecut:在发生剪切操作前触发;
  • cut:在发生剪切操作的时候触发;
  • beforepaste:在发生粘贴操作前触发;
  • paste:在发生粘贴操作的时候触发。

在实际的事件发生之前,通过beforecopy、beforecut和beforepaste事件,可以在向剪贴板发送数据,或者从剪贴板取得数据之前修改数据。

二. 访问剪贴板数据:clipboardData对象

要访问剪贴板中的数据,可以通过clipboardData对象:

  • 在IE中,clipboardData对象是window对象的属性;
  • 而在Chrome、Safari和Firefox 4+中,clipboardData对象是相应event对象的属性。

但是,在Chrome、Safari和Firefox 4+中,只有在处理剪贴板事件期间,clipboardData对象才有效,这是为了防止对剪贴板的未授权访问;在IE中,则可以随时访问clipboardData对象。为了确保跨浏览器兼容,最好只在发生剪贴板事件期间使用clipboardData对象

2.1 clipboardData对象的方法:

 

  • getData()
  • setData()
  • clearData()

2.1.1 getData()

getData()方法用于从剪贴板中获取数据,它接收一个参数,即要取得的数据格式。

  • 在IE中,有两种数据格式:”text”和”URL”。
  • 在Chrome、Safari和Firefox 4+中,这个参数是一种MIME类型。不过,可以用”text”代表”text/plain”。
//获取剪贴板数据方法
function getClipboardText(event){
    var clipboardData = event.clipboardData || window.clipboardData;
    return clipboardData.getData("text");
};

2.1.2 setData()

setData()方法的第一个参数也是数据类型,第二个参数是要放在剪贴板中的文字。

对于第一个参数,IE照样是支持”text”和”URL”,而在Chrome、Safari中,仍然支持MIME类型。但是与getData()方法不同的是,在Chrome、Safari中的setData()方法不能识别”text”类型。

在成功将文本放到剪贴板中后,该方法会返回true,否则返回false。

//设置剪贴板数据
function setClipboardText(event, value){
    if(event.clipboardData){
        return event.clipboardData.setData("text/plain", value);
    }else if(window.clipboardData){
        return window.clipboardData.setData("text", value);
    }
};

2.2 clipboardData对象的属性:

属性类型说明
dropEffectString默认是 none。
effectAllowedString默认是 uninitialized。
FilesFileList粘贴操作为空List。
itemsDataTransferItemList剪切板中的各项数据。
typesArray剪切板中的数据类型。

2.2.1 items属性:

items是一个DataTransferItemList对象,自然里面都是DataTransferItem类型的数据了。

属性

items的DataTransferItem有两个属性 kind 和 type:

属性说明
kind一般为string或者file。
type具体的数据类型,例如具体是哪种类型字符串或者哪种类型的文件,即MIME-Type。

方法

方法参数说明
getAsFile如果kind是file,可以用该方法获取到文件
getAsString回调函数如果kind是string,可以用该方法获取到字符串,字符串需要用回调函数得到,回调函数的第一个参数就是剪切板中的字符串

2.2.2 types属性:

一般types中常见的值有text/plain、text/html、Files。

说明
text/plain普通字符串。
text/html带有样式的html。
Files文件(例如剪切板中的数据)。
<input type="text" id="input">

document.querySelector("#input").addEventListener("paste", function(e) {
    var clipboardData = e.clipboardData || window.clipboardData,
        i = 0,
        items,
        item,
        types;

    if( clipboardData ) {
        items = clipboardData.items;
        if( !items ) {
            return;
        }
        item = items[0];

        // 保存在剪贴板中的数据类型
        types = clipboardData.types || [];
        for(i = 0; i < types.length; i++ ) {
            if( types[i] === 'Files' ) {
                item = items[i];
                break;
            }
        }

        // 判断是否为图片数据
        if( item && item.kind === 'file' && item.type.match(/^image\//i) ) {
            alert("This is an image.");
        }
    }
});

2.3 clipboardData对象的兼容性

clipboardData对象的兼容性如下: http://caniuse.com/#search=Clipboard

1475560072-8339-e-1au6rgnf5cn7etf1kt01cptvm9

三. 复制文本到剪贴板:document.execCommand()

当文档对象被转换为设计模式的时候(选中,设置contentEditable等),文档对象提供了一个execCommand方法,通过给这这个方法传递参数命令可以操作可编辑区域的内容。这个方法的命令大多数是对文档选中区域的操作 (如bold, italics等),通过执行execCommand 方法可以对当前活动元素进行很多操作。

3.1 语法:

bool = document.execCommand(aCommandName, aShowDefaultUI, aValueArgument)

参数如下:

  • aCommandName : 命令的名称,如”cut”、”copy”、”paste”等命令
  • aShowDefaultUI : 否展示用户界面,默认为false。Mozilla没有实现。
  • aValueArgument : 一些命令需要一些额外的参数值(如insertimage需要提供这个image的url)。默认为null。

对于复制文本到剪切板,用到的方法是:

document.execCommand("copy", "false", null);

在调用之前,可以使用 document.queryCommandSupported("copy");document.queryCommandEnabled("copy");方法(这两个方法功能相同)来检测浏览器是否支持复制命令。

需要注意的是,Chrome 虽然支持复制命令的,但在 Chorme 中这两个方法都会返回 false 值。检测 document.execCommand 方法是否存在也是一个判断方法,但更好的做法是将 document.execCommand(“copy”) 调用放在 try-catch 块内。

// 选中 #myEle 标签中的文本
var myEle = document.getElementById('#myEle'),
    range = document.createRange();

range.selectNode(myEle);
window.getSelection().addRange(range);

try {
    if(document.execCommand) {
        // 复制选中的文字到剪贴板
        document.execCommand("copy", "false", null);
    }
} catch {
    // 不支持复制命令
}

应用实例:将剪切板中的图片资源显示到页面上

<input type="text" id="input" placeholder="请粘贴图片到文本框中">


// 将图片资源显示到页面中
function showImage(imageData) {
    var reader = new FileReader();
    reader.onload = function(e){
        var img = new Image();
        img.src = e.target.result;
        document.body.appendChild(img);
    };
    // 读取图片文件
    reader.readAsDataURL(imageData);
}

document.querySelector("#input").addEventListener("paste", function(e){
    var clipboardData = e.clipboardData,
        items,
        item,
        types;

    if(clipboardData){
        items = clipboardData.items;
        if(!items){
            return;
        }
        item = items[0];
        // 保存在剪贴板中的数据类型
        types = clipboardData.types || [];
        for(var i = 0; i < types.length; i++ ){
            if(types[i] === "Files"){
                item = items[i];
                break;
            }
        }
        // 判断是否为图片数据
        if( item && item.kind === 'file' && item.type.match(/^image\//i) ){
            var blob = item.getAsFile();
            showImage(blob);
        }
    }
});

查看效果:http://codepen.io/dengzhirong/embed/PGOjxm/?height=300&theme-id=15149&default-tab=result&embed-version=2

  • 版权声明: 本文源自 子匠_Zijor, 于2个月前,由整理发表,共 4383字。
  • 原文链接:点此查看原文

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: