关于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)

                        }

                    }

                }

            }

        }

    }

};

本文永久更新链接地址

相关内容