手机端编辑器总结

项目背景

由于公司业务是做书籍阅读类的。所以产品提出要在webapp的发帖页面中,能输入文本,插入图片,和插入书籍。

采坑过程

本来手机端做编辑器可以用现成的插件,文本和图片都是比较容易解决。但是为了插入书籍,只有自己来做这个功能。

坑 One

输入框用div的contenteditable属性来做,但是在输入框中输入enter键换行时,换行的文本无法获得焦点,是因为换行时会自动生成div,但生成的div并没有contenteditable属性,于是就监听enter键事件,阻止默认事件,动态重新创建contenteditable的div。

坑 Two

删除时,删到开头,要把光标移到上一个文本div。需要监听delete键,手动去删除空白的div,再把光标移动到上一个文本的末尾。iphone端表现良好,但是安卓端无法监听到delete键,所以就意识到用div还是不可行的。

于是,还是要尝试用原生的textarea,插入文本就是插入textarea,插入图片和书籍就是在文本节点下面插入图片和书籍节点,但在图片和书籍节点后面要再插入个空白的textarea可以让其继续输入。

但是textarea的缺点在于无法动态改变他的高度,但是在网上找到个方案,核心代码如下:

1
2
3
4
<div class="expandingArea" data-type="textarea">
<pre><span></span><br></pre>
<textarea data-type="text"></textarea>
</div>

每一个创建的textarea标签都需要这样包裹一下,为的是让其可以自适应高度。

以上代码在输入textarea时,监听input事件,把textarea的value复制给span标签,expandingArea用相对定位,expandingArea的高度由span标签撑开,span的高度可以跟随文本变化,span的文本又是跟textarea保持一致。这样便可以实现textarea的高度自适应了。但是要注意一点:textarea和pre里的字体样式必须保持一致

css代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
.expandingArea {
position: relative;

/*textarea和pre里的字体样式必须保持一致*/
textarea,
pre {
margin: 0;
padding: 0;
outline: 0;
border: 0;
font-size: 15px;
line-height: 17px;
min-height: 15px;
color: #474e58;
width: 100%;
white-space: pre-wrap;
word-wrap: break-word;
}

textarea {
position: absolute;
top: 0;
left: 0;
height: 100%;
resize: none;
overflow: hidden;
}
pre {
display: block;
visibility: hidden;
}
}

插入书籍时,拿到书籍的json然后生成一个div放置在文本div下面,并在书籍div后生成一个新的空白文本div,这样就可以继续在书籍下面输入文本,当删除文本时,假如删到开头,就把当前文本的value附加给上一个文本div,再删除当前的文本节点。这样整个需求算是完成了。

(完)