怎么控制contenteditable的输入

contenteditable是所有流浪器都支持的属性, 可以利用标签模拟文本域, 实现体验相当不错的内容跟着高度自动增高的体验, 但是也带来一些问题, 就是可以直接复制带有style样式的标签进去

之前有看到过文章过滤HTML的方法, 就是在复制进去后将HTML过滤掉, 这样做的问题是过滤的标签多了之后,会有很明显的感觉, 还有就是, 当光标的位置发生变化之后, 会导致位置不正确

控制contenteditable只能输入纯文本才是一种比较好的体验

一. 用CSS控制

一个div标签要让其可编辑, 直接添加contenteditable属性就可以, 但是你可能不知道还可以通过css来约束它的输入内容

user-modify: read-only;
user-modify: read-write;
user-modify: write-only; /*几乎没有流浪器支持*/
user-modify: read-write-plaintext-only;

read-only表示只读, read-write表示可读写, 和不设置没啥区别, write-only表示只写, 到目前为止几乎没有流浪器支持该属性, 估计以后也不会有, read-write-plaintext-only表示可读可写,但是只能写入纯文本

不用说, 这些标签都是要加私有前缀的

使用user-modify: read-write-plaintext-only; 就可以完美解决只输入文本的需求

二. 使用contenteditable的其他属性值来控制

what??? contanteditable除了true和false还有别的值吗, 答案是当然有的, 新的草案已经明确提出了还有多个其他属性值, 其中有这么一段话

展开之后就是

contenteditable=""
contenteditable
="events" contenteditable="caret"
contenteditable="typing"
contenteditable="plaintext-only" contenteditable="true" contenteditable="false"

其中不包括inherit, events, caret, typing, 可能是流浪器还没有支持, 毕竟现在只是草案, 至于能干什么我也不知道, 但是 plaintext-only 这个属性是 Chrome已经支持了的, 就死控制只能输入纯文本, 如果你发现居然可以复制进去富文本, 那么你一定用的不是Chrome流浪器

三. 控制粘贴 paste 时间的js控制方法

如果我们单纯的敲击键盘, 输入的内容实际上都是纯文本, 除了IE流浪器下会自动把输入框里面符合url的地址自动加上连接, 富文本污染的情况主要出现在复制粘贴的时候, 那么如果我们能在粘贴之前, 在剪切板内把HTML内容给过滤, 再手动插入到编辑框里, 不就可以了吗

于是有这么一段代码可以完美解决

$('[contenteditable]').each(function() {
    // 干掉IE http之类地址自动加链接
    try {
        document.execCommand("AutoUrlDetect", false, false);
    } catch (e) {}
    $(this).on('paste', function(e) {
        e.preventDefault();
        var text = null;
        if(window.clipboardData && clipboardData.setData) {
            // IE
            text = window.clipboardData.getData('text');
        } else {
            text = (e.originalEvent || e).clipboardData.getData('text/plain') || prompt('在这里输入文本');
        }
        if (document.body.createTextRange) {
            if (document.selection) {
                textRange = document.selection.createRange();
            } else if (window.getSelection) {
                sel = window.getSelection();
                var range = sel.getRangeAt(0);
                
                // 创建临时元素,使得TextRange可以移动到正确的位置
                var tempEl = document.createElement("span");
                tempEl.innerHTML = "&#FEFF;";
                range.deleteContents();
                range.insertNode(tempEl);
                textRange = document.body.createTextRange();
                textRange.moveToElementText(tempEl);
                tempEl.parentNode.removeChild(tempEl);
            }
            textRange.text = text;
            textRange.collapse(false);
            textRange.select();
        } else {
            // Chrome之类浏览器
            document.execCommand("insertText", false, text);
        }
    });
    // 去除Crtl+b/Ctrl+i/Ctrl+u等快捷键
    $(this).on('keydown', function(e) {
        // e.metaKey for mac
        if (e.ctrlKey || e.metaKey) {
            switch(e.keyCode){
                case 66: //ctrl+B or ctrl+b
                case 98: 
                case 73: //ctrl+I or ctrl+i
                case 105: 
                case 85: //ctrl+U or ctrl+u
                case 117: {
                    e.preventDefault();    
                    break;
                }
            }
        }    
    });
});

目前经过测试, 在IE9, Chrome, 火狐, 安卓, IOS上,均没有发现问题

jQuery只是为了便于书写, 核心代码与jQuery无关

document.execCommand("AutoUrlDetect", false, false); 是为了处理IE浏览器自动添加链接

原文地址:https://www.cnblogs.com/shenjp/p/8621620.html