如何让contenteditable元素只能输入纯文本

如何让contenteditable元素只能输入纯文本,第1张

一、温故而知新

很多年以前,稍等,让我 搜一下contenteditable (右上角),哈,是2010年的时候,写了篇文章“ div模拟textarea文本域轻松实现高度自适应 ”,就是说的 contenteditable 的应用。

虽然说,利用全浏览器都支持的 contenteditable 模拟文本域可以实现体验相当不错的高度跟随内容自动撑开的效果,但是呢,有个很大的问题就是HTML内容可以直接被粘贴进去,如下图所示:

之前的文章提到过过滤HTML的方法,保证内容都是纯文本。然而,这种方法的问题在于:

粘贴完毕到过滤结束有时间差,用户很看到内容一闪而过的糟糕体验;

光标的位置会发生变化,不是之前focus的位置了;

当年的我图样图森破,所以,只有上面这种程度。实际上,控制 contenteditable 元素只能输入纯文本是有体验比较好的方法的。

二、与contenteditable属性无关的CSS控制法

一个div元素,要让其可编辑,也就是可读写, contenteditable 属性是最常用方法,做前端的基本上都知道。但是,知道CSS中有属性可以让普通元素可读写的的同学怕是就少多了。

主角亮相: user-modify

支持属性值如下:

user-modify: read-only;

user-modify: read-write;

user-modify: write-only;

user-modify: read-write-plaintext-only;

其中, write-only 不用在意,当下这个年代,基本上没有浏览器支持,以后估计也不会有。 read-only表示只读,就是普通元素的默认状态啦。然后, read-write 和 read-write-plaintext-only 会让元素表现得像个文本域一样,可以 focus 以及输入内容。

您可以狠狠地点击这里: CSS user-modify属性行为表现demo

会发现,设置了 read-write 和 read-write-plaintext-only 值的两个 <p> 标签元素是可以被focus的:

而这两者的区别就在于,一个可以输入富文本,而下面一个只能输入纯文本,例如,我们从某网页同时复制一段内容粘贴进去看看:

好了,至此,本文标题的答案实际上就已经有了。也就是给元素设置:

user-modify: read-write-plaintext-only

就可以让元素既可以编辑,也只能输入纯文本,表现得就跟 textarea 文本域一样。

是不是很酷啊!然而,抱歉地跟大家讲下,目前只有webkit内核浏览器才支持read-write-plaintext-only 这个值,因此,我们的使用其实是:

-webkit-user-modify: read-write-plaintext-only

我们可以在移动端使用,以及,只需要兼顾webkit内容的桌面网页项目。

三、使用标准contenteditable属性值的HTML控制法

咳咳,提问:在HTML中, contenteditable 支持的属性值是?

图样图森破时候的我,脑中就只有 contenteditable="true" 和 contenteditable="false" ,科科,后来我发现自己太天真了, 新的草案 中明确表示还有多个其他属性值:

The contenteditable attribute is an enumerated attribute whose keywords are the empty string (“”), “events”, “caret”, “typing”, “plaintext-only”, “true”, and “false” There is one additional state, the inherit state, which is the missing value default (and the invalid value default)

垂直展示下就是(不包括默认的inherit继承):

contenteditable=""

contenteditable="events"

contenteditable="caret"

contenteditable="plaintext-only"

contenteditable="true"

contenteditable="false"

别问我,我也不知道 "events" 和 "caret" 是干什么用的,嘿,但是 "plaintext-only" 我是知道的,可以让编辑区域只能键入纯文本。这里就不需要demo了,直接下面的框框,大家可以试试,看看能不能搞富文本。

<div contenteditable="plaintext-only"></div>

如果您发现,居然出乎意料,可以弄进去富文本,那说明你使用的是非chrome之流的浏览器。

换句话说, contenteditable="plaintext-only" 和CSS只的-webkit-user-modify: read-write-plaintext-only 一样,目前仅仅是Chrome浏览器支持比较好的。

所以,您的项目如果还有很多IE8浏览器的用户,我只能替你惋惜,美妙的东西无法立即用上,不得已,寻求下面的方法。

四、控制粘贴paste事件的JS控制法

如果我们单纯地敲击键盘,输入的内容实际上都是纯文本。除了一些特殊情况,例如IE浏览器下的编辑框会自动把合乎条件的url地址自动加上链接。富文本污染的情况主要出现在复制粘贴的时候,于是,如果我们能在粘贴的时候,对剪切板中的内容进行HTML过滤,再手动插入内容,岂不就可以完美解决无法输入富文本的问题了吗!?

于是,鄙人不才,一番折腾,弄出了下面的代码:

$('[contenteditable]')each(function() {

// 干掉IE >

如果是 <input> <textarea> 一类输入框, 内部纯文本, 比较好模拟

我的方案是使用相同的样式, 维护一份拷贝, 取出标签的宽度即可,

复杂一些的话就在结尾加一个标签, 能从标签获取到光标的位置

windowgetSelction()getRangeAt(0)startOffset 去取位置,

sel = getSelection()

documentonclick = function(event) {

 eventpreventDefault();

 range = new Range;

 rangeselectNode(eventtarget);

 selremoveAllRanges();

 seladdRange(range)

}

documentonclick = function(event) {

 eventpreventDefault()

 consolelog(eventtargetgetClientRects()[0])

}

Selection 对应的是界面上的选中内容, 而 Range 是 Selection 当中的一个选中的区域

简单的理解是, 一个 Selection 里会有多个 Range, Range 包含起始位置结束位置等等,

起始未知需要知道在哪个节点, 偏移量是多少等等

当然还有根据 Selection 跟 Range 用上面的位置信息来 *** 作的 API

具体 *** 作的代码大概要结合 StackOverflow 上具体的用例来理解的了

简单的自己写一个比如, 选中点击位置

这个两个 API 的兼容性有一些问题, 比如 new Range 会在 Safari 保存,

比如 rangebaseNode 在 Firefox 下不存在

为了减少兼容性造成的影响, 可以用 rangy 这个模块:

>

有点答跑题了 后面回到重点 答案在 MDN 关于这两个 API 的文档当中,

在 Range 的示例当中, 有试验的新 API 来提供对应的功能

>

RangegetBoundingClientRect()

Returns a ClientRect object which bounds the entire contents of the Range; this would be the union of all the rectangles returned by rangegetClientRects()

RangegetClientRects()

Returns a list of ClientRect objects that aggregates the results of ElementgetClientRects() for all the elements in the Range

这两个 API 就可以返回选中的 range 的像素位置了

然后按照文档的提示, 对于元素还有 getClientRects 这个 API 可以用于获取标签的像素位置:

>

The ElementgetClientRects() method returns a collection of rectangles that indicate the bounding rectangles for each box in a client

写个脚本测试一下, 确实 OK:

关于具体用例看网上的文章: >

关于浏览器兼容性可以看这里, 似乎蛮好的: >

1、如图位置是一个html中的可编辑内容的div标签,在里边输入文字,会有一个光标。

2、通过getSelection可以获得一个Selection对象,如图。因为是一个光标,anchor和focus(选择的起点和终点)一样,偏移也一样。

3、如图,则进行文字选择,而且是跨行选择,以第一行为起点,第二行为终点,选择文字。

4、再次getSelection,可以看到anchorNode是起始节点,anchorOffset是起始偏移,focus是结束的。

5、如果从第二行倒着选到第一行,使用getSelection获取选择区域,可以看到anchorNode和focusNode和刚才相比,互换了。

6、使用一个node的textContent属性可以获得文字。结合focusOffset和anchorOffset,实际上可以获取光标/选中区域前后的文字。

7、将起始和结束位置设置为相同,而且都在结束节点的末尾。即变成闪烁光标。

以上就是关于如何让contenteditable元素只能输入纯文本全部的内容,包括:如何让contenteditable元素只能输入纯文本、ckeditor怎么获取纯文本内容、HTML contenteditable 标签里怎样获取光标像素位置等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/9642968.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-30
下一篇 2023-04-30

发表评论

登录后才能评论

评论列表(0条)

保存