JS复制到剪贴板之意料之外的坑

有些浏览器对新API的兼容实在是太差啦!

spark1e ·

不多说,直接先上代码,

function copy2Clipboard(content) {
    function useClipboardApi(content) {
        navigator.clipboard.writeText(content).then(
            () => {
                console.log('success');
            },
            () => {
                console.log('failed');
                console.log(arguments);
                useExecCommandApi(content);
            }
        ).catch(e => {
            console.log(e)
        })
    }

    function useExecCommandApi(content) {
        console.log('use execCommand fallback');
        var i = document.createElement("input")
        i.setAttribute("style", "position:absolute;z-index:-1;width:1px;height:1px;top:-1px;opacity:0;-webkit-user-select: text;")
        document.body.appendChild(i)
        i.value = content
        var t = i.contentEditable,
            n = i.readOnly,
            o = document.createRange();
        i.contentEditable = !0
        i.readOnly = !1
        o.selectNodeContents(i);
        var a = window.getSelection();
        a.removeAllRanges()
        a.addRange(o)
        i.setSelectionRange(0, 999999)
        i.contentEditable = t
        i.readOnly = n
        window.document.execCommand("Copy")
        i.blur()
        document.body.removeChild(i)
        i = null
    }


    try {
        if (window.navigator && window.navigator.clipboard) {
            useClipboardApi(content);
        } else {
            useExecCommandApi(content);
        }
    } catch (e) {
        console.log(e);
        useExecCommandApi(content);
    }
}

  1. 部分浏览器对navigator.clipboard支持很差,建议用else的代码;
  2. Safari如果要访问剪贴板,需要在可信的HTTPS环境下执行,自签的证书是无法调用execCommand/avigator.clipboard.writeText
附录:一个之前写的有注释的版本
function copyToClipboard(text) {
    if (text === "") return;
    var ipt = document.createElement('input'); // maybe you need to change `input` to `textarea`
    ipt.setAttribute(
        'style',
        'position:absolute;z-index:-1;width:1px;height:1px;top:-1px;opacity:0;-webkit-user-select: text;'
    )
    document.body.appendChild(ipt)
    ipt.value = text
    // ipt.select()
    if (/iphone|ipad|ios/.test(navigator.userAgent.toLowerCase())) {
        var oldContentEditable = ipt.contentEditable
        var oldReadOnly = ipt.readOnly
        var range = document.createRange()

        ipt.contentEditable = true
        ipt.readOnly = false
        range.selectNodeContents(ipt)

        var s = window.getSelection()
        s.removeAllRanges()
        s.addRange(range)

        ipt.setSelectionRange(0, 999999) // A big number, to cover anything that could be inside the element.

        ipt.contentEditable = oldContentEditable
        ipt.readOnly = oldReadOnly
    } else {
        ipt.select()
    }
    window.document.execCommand('Copy')
    ipt.blur()
    document.body.removeChild(ipt)
    ipt = null
}
JS复制到剪贴板之意料之外的坑
本文作者
spark1e
发布于
2023-06-02
许可协议
转载或引用本文时请遵守许可协议,注明出处、不得用于商业用途!
评论区 - Powered by Giscus