关于Javascript中的复制

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

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

使用clipboardData方法

<script language="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

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/

时间: 2024-11-05 06:34:00

关于Javascript中的复制的相关文章

实现一个函数clone,使JavaScript中的5种主要的数据类型(包括Number、String、Object、Array、Boolean)进行值复制

实现一个函数clone,可以对JavaScript中的5种主要的数据类型(包括Number.String.Object.Array.Boolean)进行值复制. 1 /** 对象克隆 2 * 支持基本数据类型及对象 3 * 递归方法 */ 4 function clone(obj) { 5 var o; 6 switch (typeof obj) { 7 case "undefined": 8 break; 9 case "string": o = obj + &q

【转】JavaScript中的对象复制(Object Clone)

JavaScript中并没有直接提供对象复制(Object Clone)的方法.因此下面的代码中改变对象b的时候,也就改变了对象a. a = {k1:1, k2:2, k3:3}; b = a; b.k2 = 4; 如果只想改变b而保持a不变,就需要对对象a进行复制. 用jQuery进行对象复制 在可以使用jQuery的情况下,jQuery自带的extend方法可以用来实现对象的复制. a = {k1:1, k2:2, k3:3}; b = {}; $.extend(b,a); 自定义clone

深度解析javascript中的浅复制和深复制

原文:深度解析javascript中的浅复制和深复制 在谈javascript的浅复制和深复制之前,我们有必要在来讨论下js的数据类型.我们都知道有Number,Boolean,String,Null,Undefined,Object五种类型.而Object又包含Function,Array和Object自身.前面的五种类型叫做基本类型,而Object是引用类型.可能有人就要问,为什么要分基本类型和引用类型呢?后面你就会明白的. 我们首先来看看浅复制和深复制的简洁定义: 深复制:直接将数据复制给

JavaScript 中的对象深度复制(Object Deep Clone)

JavaScript中并没有直接提供对象复制(Object Clone)的方法. JavaScript中的赋值,其实并不是复制对象,而是类似`c/c++`中的引用(或指针),因此下面的代码中改变对象b中的元素的时候,也就改变了对象a中的元素. a = {k1:1, k2:2, k3:3}; b = a; b.k2 = 4; 如果只想改变b而保持a不变,就需要对对象a进行复制. 用jQuery进行对象复制 在可以使用jQuery的情况下,jQuery自带的extend方法可以用来实现对象的复制.

JavaScript中的对象复制(Object Clone)

JavaScript中并没有直接提供对象复制(Object Clone)的方法.因此下面的代码中改变对象b的时候,也就改变了对象a. a = {k1:1, k2:2, k3:3};b = a;b.k2 = 4; 如果只想改变b而保持a不变,就需要对对象a进行复制. 用jQuery进行对象复制 在可以使用jQuery的情况下,jQuery自带的extend方法可以用来实现对象的复制. a = {k1:1, k2:2, k3:3};b = {};$.extend(b,a); 自定义clone()方法

JavaScript中对象的浅复制和深复制

在JavaScript中,如果要复制一个变量我们应该怎么做呢?下面这种做法是最简单的一种形式: //把a复制给b let a = 12; let b = a; 这种复制方法只能适用于基本类型,如果a是对象怎么办呢?我们先来看看上面的代码在内存中做了什么事: 声明了变量a = 12,栈内存会分配一块区域来存储,如上图所示.把a赋给b,会在栈中重新开辟一块区域来存储b,并且b的值就是a的值. 假如a是对象,内存做了什么事呢?来看下面的例子: let a = {}; let b = a; 如图所示,对

HTML5 完美解决javascript中iphone手机和android手机复制文本到剪切板问题

1.执行以下解决方案条件:(这个是原理) ①执行复制方法时 所复制文字不能被任何 块级元素和行内块元素和行内元素遮盖否则无效:(解决方案:将文本通过绝对定位或其他方式移除屏幕外) ②ios中不能复制属性值,只能复制文本元素节点:(解决方案:可以把文字颜色设成背景色就能达到隐藏看不见的效果不影响显示): 直接上代码:以下是伪代码 js代码: function img() { if (navigator.userAgent.match(/(iPhone|iPod|iPad);?/i)) {//区分i

转---深入浅出妙用 Javascript 中 apply、call、bind

作者:伯乐在线专栏作者 - chokcoco 如有好文章投稿,请点击 → 这里了解详情 如需转载,发送「转载」二字查看说明 这篇文章实在是很难下笔,因为网上相关文章不胜枚举. 巧合的是前些天看到阮老师的一篇文章的一句话: "对我来说,博客首先是一种知识管理工具,其次才是传播工具.我的技术文章,主要用来整理我还不懂的知识.我只写那些我还没有完全掌握的东西,那些我精通的东西,往往没有动力写.炫耀从来不是我的动机,好奇才是." 对于这句话,不能赞同更多,也让我下决心好好写这篇,网上文章虽多,

【转载】在Javascript中 声明时用&quot;var&quot;与不用&quot;var&quot;的区别

原文链接:http://www.2cto.com/kf/201204/128406.html[侵删] Javascript声明变量的时候,虽然用var关键字声明和不用关键字声明,很多时候运行并没有问题,但是这两种方式还是有区别的 Javascript声明变量的时候,虽然用var关键字声明和不用关键字声明,很多时候运行并没有问题,但是这两种方式还是有区别的.可以正常运行的代码并不代表是合适的代码. var num = 1: 是在当前域中声明变量. 如果在方法中声明,则为局部变量(local var