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浏览器自动添加链接