利用剪切板JS API优化输入框的粘贴体验

这篇文章发布于 2018年09月9日,星期日,16:17,归类于 JS实例。 阅读 6818 次, 今日 24 次 22 条评论

 

一、目前现在的体验问题

剪切板粘贴优化缩略图

输入框输入内容我们有时候为了方便,会直接粘贴内容,例如IP,网址,或者陌生人的手机号。但是,有时候我们复制的内容包含冗余信息,或者格式不准确,还需要重新编辑,体验就不好了。

举两个真实案例:

1. 阿里云域名解析,结果粘贴后下面这这样:

粘贴后前面有空格

从网页中复制内容的时候,不小心前面多复制了一个长空格,结果出现了格式报错,我们还需要重新删除前面空格,如果我们粘贴的时候直接过滤前后空格,体验岂不更好!

2. 简历中的手机号码,候选人经常会空格或者短横线进行3-4-4分隔,复制后粘贴,结果也失败了:

简历代码复制

粘贴的手机号码报错

如果直接剪切板中过滤到手机号以外乱七八糟的字符,岂不是少去重新编辑的烦恼,用户体验大大提升,用户一看,我明明复制的是不合法的手机号,粘贴进来进来变成合法11位数字,好神奇,体验好好,对这个产品刮目相看,微博,朋友圈,同事圈大肆宣传,其价值就不可估量了。

二、JS改变剪切板内容

我们可以利用Clipboard API改变剪切板内容,从而提高输入框粘贴信息的交互体验。

大体上,该API浏览器都有所支持,但都是部分支持,不过,本来就是增强体验的东西,就算只有一个浏览器支持,也是可以用起来的。

剪切板API兼容性

一段简易的处理代码
下面这段JavaScript代码实现的是针对输入框的的粘贴处理(IE9+支持)。然后演示了邮箱,手机号剪切板数据的简单过滤处理,其他场景大家可以自行补充。

MIT协议,大家可以随意复制粘贴,只要前面一段版权溯源注释代码保留即可。

/**
@description 表单输入框粘贴体验优化,出处https://www.zhangxinxu.com/wordpress/?p=8003
@author zhangxinxu
*/
// 遍历所有的输入框
[].slice.call(document.querySelectorAll('input, textarea')).forEach(function (ele) {
    ele.addEventListener('paste', function (event) {
        // 输入框类型
        var type = this.getAttribute('type') || this.type;
        // 剪切板数据对象
        var clipboardData = event.clipboardData || window.clipboardData;
        // 粘贴内容
        var paste = '';
        // 剪切板对象可以获取
        if (!clipboardData) { return; }
        // 获取选中的文本内容
        var textSelected = '';
        if (window.getSelection) { 
            // 现代浏览器
            // 直接window.getSelection().toString()对于IE的输入框无效
            textSelected = this.value.slice(ele.selectionStart, ele.selectionEnd);
        } else if (document.selection) { 
            // 旧IE浏览器
            textSelected = document.selection.createRange().text;
        }
        // 只有输入框没有数据,或全选状态才处理
        if (this.value.trim() == '' || textSelected === this.value) {
            // 阻止冒泡和默认粘贴行为
            event.preventDefault();
            event.stopPropagation();
            // 获取粘贴数据
            paste = clipboardData.getData('text') || '';
            // 进行如下处理
            // 除非是password,其他都过滤前后空格
            if (type != 'password') {
                paste = paste.trim();
            }
            // 邮箱处理,可能会使用#代替@避免被爬虫抓取
            if (type == 'email') {
                paste = paste.replace('#', '@');
            } else if (type == 'tel') {
                // 手机号处理
                paste = paste.replace(/^\+86/, '');
                // 如果此时剩余所有数字正好11位
                if (paste.match(/\d/) && paste.match(/\d/g).length == 11) {
                    paste = paste.replace(/\D/g, '');
                }    
            } // 其他类型处理大家自行补充...
            
            // 插入
            this.value = paste;
        }
    });    
});

实现效果如下demo,您可以狠狠地点击这里:输入框粘贴文本优化demo

例如,复制demo页面手机输入框后面的手机号码,然后粘贴到输入框中,会看到中间的短横线自动被过滤了。

手机号复制粘贴自动过滤截图

其它
上面代码对剪切板内容的处理比较简单,就是过滤前后空格,邮箱#替换成@,手机号11位标准格式化。大家可以根据实际需求进行更好的处理,例如,XSS过滤可以直接在剪切板中进行等。

补充于2018-09-30 拖拽输入优化
当我们拖拽文本进入输入框的时候,也可以做类似的优化,效果如下GIF:

手机号拖拽优化

相关JavaScript代码如下:

input.addEventListener('drop', function (event) {
    // 获取拖拽文本内容
    var text = event.dataTransfer.getData('text');
    if (this.value == '' && text.match(/\d/g) && text.match(/\d/g).length == 11) {
        event.preventDefault();
        input.value = text.replace(/\D/g, '');
        input.select();
    }
});

您可以狠狠地点击这里:优化手机号拖拽输入体验demo

三、临了说说copy与剪切板

基于剪切板JS API可以做的事情不仅仅是粘贴,复制的时候也可以做些事情,例如,我可以在我的网站页面上绑定一个copy事件,当你复制文章内容的时候,自动在剪切板文字后面加上一段版权声明。

代码示意:

document.addEventListener('copy', function (event) {
    var clipboardData = event.clipboardData || window.clipboardData;
    if (!clipboardData) { return; }
    var text = window.getSelection().toString();
    if (text) {
        event.preventDefault();
        clipboardData.setData('text/plain', text + '\n\n鑫空间版权所有');
    }
});

您可以狠狠地点击这里:复制页面文字内容自动携带版本声明demo

复制demo页面任意一段文字,然后粘贴到输入框中,可以看到粘贴内容最后附有“鑫空间版权所有”这样的信息,如下截图:

复制内容自带版权信息

不少技术博客有这样的处理,不过放心,我这边是不会加这个的,代码什么的想复制就复制好了。大家都是靠代码技能吃饭的,可以体会写代码的不易,相信一定会尊重知识劳动成果——保留出处等版权信息的。


白云飘飘,天气甚好,总能唤起年少时候同样天气里的那些美好记忆。

最近把《CSS世界》配套网站迁移到了国内,之前用的是美国的服务器(不用备案),但经常会响应迟钝。因为有论坛,备案还花了不少功夫。顺便升级成https协议了。

做垂直站点也是个不错的路数,可惜精力有限,等以后时机成熟,自己出来搞事情的时候,可以找些人一起弄弄。

算了算了,不再唠叨了,唠叨的话可以写在“生活与创作”专栏中,就这些。

小而美的小知识,希望可以对你的工作有所启发。

感谢阅读!

(本篇完)

分享到:1
×


发表评论(目前22 条评论)

  1. 流采说道:

    这个论坛真是用心了,1024 个赞

  2. 对于pre标签的复制说道:

    对于pre标签的粘贴怎么确定选中的部分

  3. czar说道:

    提高可用性,赞

  4. wusp说道:

    有BUG,先复制汉字。再复制其他的邮箱或者电话号码他就不会改变了

  5. 慢走说道:

    前段时间开始就一直在大大的博客逛啦

  6. webster说道:

    好几天没有更新了,期待中。。。

  7. 广建说道:

    这样确实省很多事情

  8. 一组麻袋某说道:

    NodeList 自带 forEach 方法 就不用call了吧

  9. DeathGhost说道:

    旭大大好厉害

  10. DeathGhost说道:

    每日一览…

  11. Aragorn说道:

    总能唤起年少时候同样天气里的那些美好记

  12. 1说道:

    厉害

  13. Ye Xu说道:

    为什么这里有个“4” ?https://cl.ly/72fe142118c3

  14. 邓慢慢说道:

    谢谢老师分享的知识,就喜欢你的不正经,张老师,教师节快乐啊,

  15. enginesp说道:

    您好,不知道如果是直接選取文字然後用拖曳的方式拖曳到輸入欄位的操作,是否有事件可以被截獲?

  16. 长江长江我是黄河说道:

    白云飘飘,天气甚好,总能唤起年少时候同样天气里的那些美好记忆。 话说,昨天的天气是真的好!!!!!!!

  17. mxm145说道:

    感谢分享,css世界 是今年读的最有收获的技术书籍

  18. WangNianyi2001说道:

    之前搞反截屏的腳本就是用的這個 API……
    (Rime 怎麼調繁簡轉換啊

  19. rrr说道:

    有意思,能不能分享下怎么让用户不点复制按钮而直接复制内容呢?比如一个异步计算器场景,能不能点『计算』按钮:通过接口拿到计算值,然后复制到剪贴板。