阅读全文你将获得以下解决方案。
- 点击长文本编辑
textarea
,自动获得焦点 - 随着输入值自动伸缩高度
- 可复制添加信息
- 可粘贴文本
- 可粘贴图片
以下实例代码执行环境为Chrome
方案一
自适应调整高度
<style>
.fix-send {
position: fixed;
bottom: 0;
left: 0;
padding: 7.5px 5px;
width: 100%;
border-top: solid 1px #eee;
background: #f5f5f5;
align-items: center;
}
.fix-send .send-input {
overflow: auto;
box-sizing: border-box;
margin: 0 0 0 5px;
padding: 9px;
height: auto;
max-height: 65px;
min-height: 34px;
outline: 0;
border: none;
border-radius: 4px;
font-size: 14px;
display: inline-block;
flex: 1;
}
</style>
<div class="fix-send flex footer-bar">
<i class="icon-face"></i>
<textarea class="send-input t-28" maxlength="2000" rows="1" id="saytext"></textarea>
<div>
<input type="file" name="pic" id="file" style="display: none">
<i class="icon-plus image_up"></i>
<span class="send-btn">发送</span>
</div>
</div>
<script>
$(".send-btn").click(function(){
var text = $(".send-input").val(); //发送输入的内容
$(".send-input").val(""); //清空输入框
$(".send-input").css("height", "34px"); //还原输入框为原始高度
})
$('textarea').each(function () {
this.setAttribute('style','height','34px;overflow-y:hidden;'); //设置初始高度
}).on('input', function () {
//输入文本时,自动调整高度
this.style.height = 'auto';
this.style.height = (this.scrollHeight) + 'px';
});
</script>
效果如下:
方案二
HTML5 Textarea 元素
1. 自动获得焦点
点击编辑自动获得焦点后光标跳转到了最前面,why?
查文档 MDN,textarea
元素存在selectionEnd
和 selectionStart
的属性用来表示选中的文本开始位置和结束位置,DOM接口实例是 HTMLTextAreaElement
, 它具有 setSelectionRange<span> </span>
方法,用来选中输入框中的文本,用法:TextAreaElement.setSelectionRange(selectionStart, selectionEnd, [optional] selectionDirection);
那么我们只要做到 selectionStart === selectionEnd === value.length<span> </span>
, 这样光标就选中到最末尾。
edit.addEventListener("click", function() {
txt.classList.add("hidden");
document.body.insertBefore(textarea, edit);
textarea.innerHTML = "这是需要编辑的信息";
textarea.focus();
// textarea.selectionEnd = textarea.innerHTML.length;
textarea.setSelectionRange(
textarea.innerHTML.length,
textarea.innerHTML.length
);
});
2. 自适应高度
当不设置高度时换行会出现滚动条,所以只要让 textarea
滚动条消失,让其 height = scrollHieght
, 那么如何监听textarea的变化,则需要 input
事件,让 textarea
高度动态等于它的 scrollHeight
即可,代码如下:
textarea.addEventListener("input", function() {
this.style.height = `${this.scrollHeight}px`;
});
为什么每次输入都会使得高度增加(每次增加4px),经过测试 Safari
同样也是这个效果,Firefox
符合预期高度不异常增加,查看Chrome控制台发现(查看 chromium) textarea
内置了很多样式,尝试将去掉 padding
后,可以正常随着内容增加高度自适应了。
<style>
textarea {
padding: 0;
}
</style>
<textarea></textarea>
<script>
const textarea = document.createElement("textarea");
textarea.addEventListener("input", function(e) {
this.style.height = `${this.scrollHeight}px`;
});
</script>
为什么去掉padding值,输入后高度就不增加了?(未找到合理的解释,欢迎留言讨论解答)
但是删除文本的情况下 height
并未能自动缩放,分析原因, 当删除文本换行的时候 scrollHeight
的大小并未发生改变,scrollHeight
作为只读属性( MDN-文档),如何让 scrollHeight
高度重新计算哪?只有改变高度,于是:
textarea.addEventListener("input", function(e) {
this.style.height = "inherit";
this.style.height = `${this.scrollHeight}px`;
});
到此高度自适应输入内容完成,但是每次换行的闪动很难受,transition
走一波,
textarea {
overflow: hidden; // 防止换行出现滚动条闪动
padding: 5px 10px;
box-sizing: border-box;
transition: all 0.2s linear;
}
结果 transition
并没效果,原因 height
初始值或者参考值必须为数值过渡动画才会生效,height
设置为 auto
或者 inherit
动画不会生效, 所以折中的办法就是当删除的时候重新重置高度,输入时不需要重置,这样输入时动画生效, 删除没有动画, 暂时没想到更好的办法。
textarea.addEventListener("keyup", function(e) {
if (e.keyCode === 8) {
this.style.height = "inherit";
this.style.height = `${this.scrollHeight}px`;
} else {
this.style.height = `${this.scrollHeight}px`;
}
});
3. 支持粘贴文本,图片等
textarea只能输入文本,无法实现粘贴图片。
textarea.addEventListener(
"paste",
function(e) {
e.preventDefault();
console.log(
"paste",
e.clipboardData.items,
e.clipboardData.types,
e.clipboardData.getData("text/html"),
e.clipboardData.getData("text/plain"),
e.clipboardData.getData("text/Files")
);
},
false
);
方案三
div contenteditable
替换textarea
1. 自动获得焦点
编辑 div contenteditable
为 true
,然后利用 Range
和 Selection
光标移动到最后的效果。
edit.addEventListener("click", () => {
textarea.setAttribute("contenteditable", true);
textarea.focus();
const range = document.createRange();
// range 包含的内容
range.selectNodeContents(textarea);
// range.setStart(textarea.firstChild, 0);
// range.setStart(textarea.lastChild, textarea.innerHTML.length);
// 起始位置是否相同
range.collapse(false);
const sel = window.getSelection();
// 将所有的区域都从选区中移除。
sel.removeAllRanges();
// 一个区域(Range)对象将被加入选区。
sel.addRange(range);
});
2. 自适应高度
div contenteditable
天然支持根据输入来自适应高度。
3. 粘贴图片, 文本等
textarea.addEventListener("paste", function(e) {
e.preventDefault();
const clipboardData = e.clipboardData || e.originalEvent.clipboardData;
// 获取纯文本
let text = clipboardData.getData("text/plain");
let file = clipboardData.getData("text/plain");
// console.log(clipboardData.items, clipboardData.getData("text/Files"));
// 插入img,可以做一些上传图片的一些操作
insertImg(clipboardData);
// 只输入纯文本
document.execCommand("insertText", false, text);
});
此方法可以限定只能上传文本或者图片。