关于Javascript中的复制
在做项目时有一个需求,是需要复制内容到剪切板,因为有众多浏览器,所以要兼容性很重要
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) } } } } } } };
参考文章
http://www.jb51.net/article/22403.htm
http://www.cnblogs.com/yangjunhua/archive/2012/09/10/2678817.html
http://jiongks.name/blog/zeroclipboard-intro/
- 作者:踏雪无痕
- 出处:http://www.cnblogs.com/chenpingzhao/
- 本文版权归作者和博客园共有,如需转载,请联系 pingzhao1990#163.com