Javascript复制实例详解


Posted in Javascript onJanuary 28, 2016

在做项目时有一个需求,是需要复制内容到剪切板,因为有众多浏览器,所以要兼容性很重要。

1、最简单的copy,只能在IE下使用

使用clipboardData方法

<script type="text/javascript">
function copy(){
window.clipboardData.setData("text",document.getElementById("name").value);
alert("The text is on the clipboard, try to paste it!");
}
</script>

2、跨浏览器的,但是Firefox无法复制

<head>
<script type="text/javascript">
function CopyToClipboard () {
var input = document.getElementById ("toClipboard");
var textToClipboard = input.value;
var success = true;
if (window.clipboardData) { // Internet Explorer
window.clipboardData.setData ("Text", textToClipboard);
}
else {
// create a temporary element for the execCommand method
var forExecElement = CreateElementForExecCommand (textToClipboard);
/* Select the contents of the element 
(the execCommand for 'copy' method works on the selection) */
SelectContent (forExecElement);
var supported = true;
// UniversalXPConnect privilege is required for clipboard access in Firefox
try {
if (window.netscape && netscape.security) {
netscape.security.PrivilegeManager.enablePrivilege ("UniversalXPConnect");
}
// Copy the selected content to the clipboard
// Works in Firefox and in Safari before version 5
success = document.execCommand ("copy", false, null);
}
catch (e) {
success = false;
}
// remove the temporary element
document.body.removeChild (forExecElement);
}
if (success) {
alert ("The text is on the clipboard, try to paste it!");
}
else {
alert ("Your browser doesn't allow clipboard access!");
}
}
function CreateElementForExecCommand (textToClipboard) {
var forExecElement = document.createElement ("div");
// place outside the visible area
forExecElement.style.position = "absolute";
forExecElement.style.left = "-10000px";
forExecElement.style.top = "-10000px";
// write the necessary text into the element and append to the document
forExecElement.textContent = textToClipboard;
document.body.appendChild (forExecElement);
// the contentEditable mode is necessary for the execCommand method in Firefox
forExecElement.contentEditable = true;
return forExecElement;
}
function SelectContent (element) {
// first create a range
var rangeToSelect = document.createRange ();
rangeToSelect.selectNodeContents (element);
// select the contents
var selection = window.getSelection ();
selection.removeAllRanges ();
selection.addRange (rangeToSelect);
}
</script>
</head>
<body>
<input id="toClipboard" value="text to clipboard"/>
<button onclick='CopyToClipboard ()'>Copy text to clipboard</button>
</body>

测试后,Firefox访问失败

3、万能的flash

不要重复造轮子了,有一个使用广泛的类库ZeroClipboard

Zero Clipboard 的实现原理

Zero Clipboard 利用 Flash 进行复制,之前有 Clipboard Copy 解决方案,其利用的是一个隐藏的 Flash。但最新的 Flash Player 10 只允许在 Flash 上进行操作才能启动剪贴板。所以 Zero Clipboard 对此进行了改进,用了一个透明的 Flash ,让其漂浮在按钮之上,这样其实点击的不是按钮而是 Flash ,也就可以使用 Flash 的复制功能了。

创建一个透明的flash

将这个flash浮在按钮上层

确定要复制的文本是什么

监听这个透明flash的鼠标点击事件

该flash被点击之后,完成剪切板处理

对于这几件事,ZeroClipboard分别提供了不同的api,来完成整个需求

如何使用 Zero Clipboard

git clone https://github.com/chenpingzhao/easycopy.git

关于ZeroClipboard.js

var ZeroClipboard = {
version: "1.0.7",
clients: {},
moviePath: "zeroclipboard.swf",
nextId: 1,
$: function(A) {
if (typeof(A) == "string") {
A = document.getElementById(A)
}
if (!A.addClass) {
A.hide = function() {
this.style.display = "none"
};
A.show = function() {
this.style.display = ""
};
A.addClass = function(B) {
this.removeClass(B);
this.className += " " + B
};
A.removeClass = function(D) {
var E = this.className.split(/\s+/);
var B = -1;
for (var C = 0; C < E.length; C++) {
if (E[C] == D) {
B = C;
C = E.length
}
}
if (B > -1) {
E.splice(B, 1);
this.className = E.join(" ")
}
return this
};
A.hasClass = function(B) {
return !!this.className.match(new RegExp("\\s*" + B + "\\s*"))
}
}
return A
},
setMoviePath: function(A) {
this.moviePath = A
},
dispatch: function(D, B, C) {
var A = this.clients[D];
if (A) {
A.receiveEvent(B, C)
}
},
register: function(B, A) {
this.clients[B] = A
},
getDOMObjectPosition: function(C, A) {
var B = {
left: 0,
top: 0,
width: C.width ? C.width : C.offsetWidth,
height: C.height ? C.height : C.offsetHeight
};
while (C && (C != A)) {
B.left += C.offsetLeft;
B.top += C.offsetTop;
C = C.offsetParent
}
return B
},
Client: function(A) {
this.handlers = {};
this.id = ZeroClipboard.nextId++;
this.movieId = "ZeroClipboardMovie_" + this.id;
ZeroClipboard.register(this.id, this);
if (A) {
this.glue(A)
}
}
};
ZeroClipboard.Client.prototype = {
id: 0,
ready: false,
movie: null,
clipText: "",
handCursorEnabled: true,
cssEffects: true,
handlers: null,
//我们可以通过下面这个api,将flash和按钮重叠,且浮在按钮之上
glue: function(D, B, E) {
this.domElement = ZeroClipboard.$(D);
var F = 99;
if (this.domElement.style.zIndex) {
F = parseInt(this.domElement.style.zIndex, 10) + 1
}
if (typeof(B) == "string") {
B = ZeroClipboard.$(B)
} else {
if (typeof(B) == "undefined") {
B = document.getElementsByTagName("body")[0]
}
}
var C = ZeroClipboard.getDOMObjectPosition(this.domElement, B);
this.div = document.createElement("div");
var A = this.div.style;
A.position = "absolute";
A.left = "" + C.left + "px";
A.top = "" + C.top + "px";
A.width = "" + C.width + "px";
A.height = "" + C.height + "px";
A.zIndex = F;
if (typeof(E) == "object") {
for (addedStyle in E) {
A[addedStyle] = E[addedStyle]
}
}
B.appendChild(this.div);
this.div.innerHTML = this.getHTML(C.width, C.height)
},
/*IE 的 Flash JavaScript 通信接口上有一个 bug 。
你必须插入一个 object 标签到一个已存在的 DOM 元素中。并且在写入 innerHTML 之前请确保该元素已经 appendChild 方法插入到 DOM 中*/
getHTML: function(D, A) {
var C = "";
var B = "id=" + this.id + "&width=" + D + "&height=" + A;
if (navigator.userAgent.match(/MSIE/)) {
var E = location.href.match(/^https/i) ? "https://" : "http://";
C += '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="' + E + 'download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="' + D + '" height="' + A + '" id="' + this.movieId + '" align="middle"><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="false" /><param name="movie" value="' + ZeroClipboard.moviePath + '" /><param name="loop" value="false" /><param name="menu" value="false" /><param name="quality" value="best" /><param name="bgcolor" value="#ffffff" /><param name="flashvars" value="' + B + '"/><param name="wmode" value="transparent"/></object>'
} else {
C += '<embed id="' + this.movieId + '" src="' + ZeroClipboard.moviePath + '" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="' + D + '" height="' + A + '" name="' + this.movieId + '" align="middle" allowScriptAccess="always" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="' + B + '" wmode="transparent" />'
}
return C
},
hide: function() {
if (this.div) {
this.div.style.left = "-2000px"
}
},
show: function() {
this.reposition()
},
destroy: function() {
if (this.domElement && this.div) {
this.hide();
this.div.innerHTML = "";
var A = document.getElementsByTagName("body")[0];
try {
A.removeChild(this.div)
} catch (B) {}
this.domElement = null;
this.div = null
}
},
/* 因为按钮上漂浮有一个 Flash 按钮,所以当页面大小发生变化时,Flash 按钮可能会错位,就点不着了
Zero Clipboard 提供了一个 reposition() 方法,可以重新计算 Flash 按钮的位置。我们可以将它绑定到 resize 事件上
bind(window, "resize", function(){ clip.reposition(); }); 
function bind(obj, type, fn) {
if (obj.attachEvent) {
obj['e' + type + fn] = fn;
obj[type + fn] = function() {
obj['e' + type + fn](window.event);
}
obj.attachEvent('on' + type, obj[type + fn]);
} else
obj.addEventListener(type, fn, false);
}*/
reposition: function(C) {
if (C) {
this.domElement = ZeroClipboard.$(C);
if (!this.domElement) {
this.hide()
}
}
if (this.domElement && this.div) {
var B = ZeroClipboard.getDOMObjectPosition(this.domElement);
var A = this.div.style;
A.left = "" + B.left + "px";
A.top = "" + B.top + "px"
}
},
setText: function(A) {
this.clipText = A;
if (this.ready) {
this.movie.setText(A)
}
},
addEventListener: function(A, B) {
A = A.toString().toLowerCase().replace(/^on/, "");
if (!this.handlers[A]) {
this.handlers[A] = []
}
this.handlers[A].push(B)
},
setHandCursor: function(A) {
this.handCursorEnabled = A;
if (this.ready) {
this.movie.setHandCursor(A)
}
},
/*鼠标移到按钮上或点击时,由于有 Flash 按钮的遮挡,所以像 css ":hover", ":active" 等伪类可能会失效。
setCSSEffects() 方法就是解决这个问题。首先我们需要将伪类改成类
copy - botton: hover {
border - color: #FF6633;
}

可以改成下面的 ":hover" 改成 ".hover"

copy - botton.hover {
border - color: #FF6633;
}

我们可以调用 clip.setCSSEffects( true ); 这样 Zero Clipboard 会自动为我们处理:将类 .hover 当成伪类 :hover*/

setCSSEffects: function(A) {
this.cssEffects = !! A
},
/*Zero Clipboard 提供了一些事件,你可以自定义函数处理这些事件。
Zero Clipboard 事件处理函数为 addEventListener(); 例如当 Flash 完全载入后会触发一个事件 "load" 
clip.addEventListener( "load", function(client) { 
alert("Flash 加载完毕!"); 
});*/
receiveEvent: function(D, E) {
D = D.toString().toLowerCase().replace(/^on/, "");
switch (D) {
case "load":
this.movie = document.getElementById(this.movieId);
if (!this.movie) {
var C = this;
setTimeout(function() {
C.receiveEvent("load", null)
}, 1);
return
}
if (!this.ready && navigator.userAgent.match(/Firefox/) && navigator.userAgent.match(/Windows/)) {
var C = this;
setTimeout(function() {
C.receiveEvent("load", null)
}, 100);
this.ready = true;
return
}
this.ready = true;
this.movie.setText(this.clipText);
this.movie.setHandCursor(this.handCursorEnabled);
break;
case "mouseover":
if (this.domElement && this.cssEffects) {
this.domElement.addClass("hover");
if (this.recoverActive) {
this.domElement.addClass("active")
}
}
break;
case "mouseout":
if (this.domElement && this.cssEffects) {
this.recoverActive = false;
if (this.domElement.hasClass("active")) {
this.domElement.removeClass("active");
this.recoverActive = true
}
this.domElement.removeClass("hover")
}
break;
case "mousedown":
if (this.domElement && this.cssEffects) {
this.domElement.addClass("active")
}
break;
case "mouseup":
if (this.domElement && this.cssEffects) {
this.domElement.removeClass("active");
this.recoverActive = false
}
break
}
if (this.handlers[D]) {
for (var B = 0, A = this.handlers[D].length; B < A; B++) {
var F = this.handlers[D][B];
if (typeof(F) == "function") {
F(this, E)
} else {
if ((typeof(F) == "object") && (F.length == 2)) {
F[0][F[1]](this, E)
} else {
if (typeof(F) == "string") {
window[F](this, E)
}
}
}
}
}
}
};

以上所述是小编给大家介绍的Javascript复制实例详解,希望对大家有所帮助。

Javascript 相关文章推荐
YUI 读码日记之 YAHOO.util.Dom - Part.1
Mar 22 Javascript
Ajax+Json 级联菜单实现代码
Oct 27 Javascript
JQuery Ajax通过Handler访问外部XML数据的代码
Jun 01 Javascript
javascript函数以及基础写法100多条实用整理
Jan 13 Javascript
同一个网页中实现多个JavaScript特效的方法
Feb 02 Javascript
JS表格组件神器bootstrap table详解(基础版)
Dec 08 Javascript
JS实现左右无缝轮播图代码
May 01 Javascript
easyui datebox 时间限制,datebox开始时间限制结束时间,datebox截止日期比起始日期大的实现代码
Jan 12 Javascript
jquery对象与DOM对象转化
Feb 08 Javascript
Angular实现svg和png图片下载实现
May 05 Javascript
如何在微信小程序中实现Mixins方案
Jun 20 Javascript
jQuery模仿ToDoList实现简单的待办事项列表
Dec 30 jQuery
基于jQuery实现以手风琴方式展开和折叠导航菜单
Jan 28 #Javascript
基于JavaScript的操作系统你听说过吗?
Jan 28 #Javascript
js+canvas绘制矩形的方法
Jan 28 #Javascript
js+canvas简单绘制圆圈的方法
Jan 28 #Javascript
谈一谈javascript闭包
Jan 28 #Javascript
JavaScript统计字符串中每个字符出现次数完整实例
Jan 28 #Javascript
基于javascript实现checkbox复选框实例代码
Jan 28 #Javascript
You might like
php+AJAX传送中文会导致乱码的问题的解决方法
2008/09/08 PHP
php删除与复制文件夹及其文件夹下所有文件的实现代码
2013/01/23 PHP
Yii实现多按钮保存与提交的方法
2014/12/03 PHP
PHP实现的mysql主从数据库状态检测功能示例
2017/07/20 PHP
php7安装mongoDB扩展的方法分析
2017/08/02 PHP
PHP后期静态绑定实例浅析
2018/12/21 PHP
php 多进程编程父进程的阻塞与非阻塞实例分析
2020/02/22 PHP
javascript 类方法定义还是有点区别
2009/04/15 Javascript
jquery刷新页面的实现代码(局部及全页面刷新)
2011/07/11 Javascript
ASP.NET jQuery 实例13 原创jQuery文本框字符限制插件-TextArea Counter
2012/02/03 Javascript
JavaScript操作DOM元素的childNodes和children区别
2015/04/01 Javascript
浅谈jquery事件处理
2015/04/24 Javascript
js实现匹配时换色的输入提示特效代码
2015/08/17 Javascript
JS中用childNodes获取子元素换行会产生一个子元素
2016/12/08 Javascript
vue中子组件向父组件传递数据的实例代码(实现加减功能)
2018/04/20 Javascript
使用JavaScript中的lodash编写双色球效果
2018/06/24 Javascript
详解Angular中实现自定义组件的双向绑定的两种方法
2018/11/23 Javascript
JS实现的图片选择顺序切换和循环切换功能示例【测试可用】
2018/12/28 Javascript
[01:45]绝对公平!DOTA2队长征召模式详解
2014/04/25 DOTA
[03:04]2018年国际邀请赛典藏宝瓶&莱恩声望物品展示 片尾有彩蛋
2018/06/04 DOTA
python实现的防DDoS脚本
2011/02/08 Python
Python不规范的日期字符串处理类
2014/06/10 Python
python根据给定文件返回文件名和扩展名的方法
2015/03/27 Python
10种检测Python程序运行时间、CPU和内存占用的方法
2015/04/01 Python
python比较2个xml内容的方法
2015/05/11 Python
python merge、concat合并数据集的实例讲解
2018/04/12 Python
Django objects的查询结果转化为json的三种方式的方法
2018/11/07 Python
Python实现字符串匹配的KMP算法
2019/04/04 Python
如何使用Python发送HTML格式的邮件
2020/02/11 Python
Django之choices选项和富文本编辑器的使用详解
2020/04/01 Python
使用Django的JsonResponse返回数据的实现
2021/01/15 Python
python实现b站直播自动发送弹幕功能
2021/02/20 Python
毕业生求职信的经典写法
2014/01/31 职场文书
典型事迹材料范文
2014/12/29 职场文书
Matplotlib可视化之添加让统计图变得简单易懂的注释
2021/06/11 Python
Spring整合Mybatis的全过程
2021/06/28 Java/Android