【留言板】可编辑输入框操作总结
时间:2022-04-22
本文章向大家介绍【留言板】可编辑输入框操作总结,主要内容包括一、定义需求、二、详细设计、三、代码实现、2. SelectionUitls类(可编辑输入框管理类)、3. LeaveMsg类(留言板管理类)、四、使用他们、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
闲暇之余,用于加深自己对基础的了解,徒手撸了一个留言板:输入框。废话少说,进入正题。简陋的效果如下(下载代码):
一、定义需求
- 可输入文本,以及插入表情。
- 兼容性:IE与标准浏览器
二、详细设计
根据需求,我们大致可以想到如下问题:
- 兼容性的处理
- 事件绑定的兼容性
- 可编辑输入框的表情插入兼容性
- 获取数据的兼容性
- 三个模块
- 留言板与ui交互的模块
- 表情展示模块
- 可编辑输入框的操作模块 因此我规划了如下的类结构:
- LeaveMsg:实现UI与留言板的交互
- FaceWrap:实现表情殂的管理,以及相应事件的响应,如显示/隐藏,获取表情,初始化表情列表等。
- SelectionUitls:实现可编辑输入框的操作,如:插入一个表情、获取数据等。 各模块的兼容性在以下细节中进行介绍。
三、代码实现
1. FaceWrap类(表情列表管理类)
var FaceWrap = function(head, cont, opts){
this.$head = head;
this.$cont = cont;
this.data = ['one', 'two', 'thr'];
var self = this;
var toggle = false;
this.onClickHandHandle = function(evt){
if(!toggle){
self.$cont.style.display = 'block';
toggle = true;
}else{
self.$cont.style.display = 'none';
toggle = false;
}
if(opts.onClickHandHandle){
opts.onClickHandHandle(toggle);
}
}
this.onChooseImg = opts. onChooseImg || function(){}
this.generalFaceImg();
this.bind();
}
var facePt = FaceWrap.prototype;
facePt.generalFaceImg = function(){
var fragment = document.createDocumentFragment();
for( var index =0; index < this.data.length; ++index){
var data = this.data[index];
var img = document.createElement('img');
img.setAttribute('src', '../img/face/' + data + '.jpg');
img.setAttribute('data-id', data);
img.setAttribute('class','face-img');
fragment.appendChild(img);
}
this.$cont.appendChild(fragment);
}
facePt.bind = function(){
if(document.attachEvent){
this.$head.attachEvent('onclick',this.onClickHandHandle);
this.$cont.attachEvent('onclick',this.onChooseImg);
}else{
this.$head.addEventListener('click',this.onClickHandHandle);
this.$cont.addEventListener('click',this.onChooseImg);
}
}
facePt.hide = function(){
this.onClickHandHandle();
}
需要注意的点:
1. 在初始化表情列表(generalFaceImg)的时候,用到了Fragment(文档碎片)来提高性能;
2. 在class中设元素的display为none后,用js是获取不到此元素的display值的。
兼容性有以下几个点:
- 事件的绑定:attacheEvent和addEventListener。
- classList在ie8-不支持的问题,暂时选择的用setAttribute代替
- appendChild全都支持,append在chrome中支持,但ie不支持
2. SelectionUitls类(可编辑输入框管理类)
var SelectionUitls = function(dom){
this.dom = dom;
this.cursorIndex;
}
var pt = SelectionUitls.prototype;
pt.insertDomForStandard = function(dom){
var sel = window.getSelection(); //获取选区集合
var range = sel.getRangeAt(0); //获取第一个选择
range.deleteContents(); //删除选区选重的元素
range.insertNode(dom); //插入元素在选区的首位置
range = range.cloneRange(); //克隆一个选区
range.setStartAfter(dom); //设置选区起点光标位置在指定元素的后面
range.collapse(true);//合并起点、终点光标
sel.removeAllRanges();//移除所有选区
sel.addRange(range); //添加一个选区
}
pt.insertDomForIe = function(dom){
this.dom.focus();
var wrap = document.createElement('div');
wrap.appendChild(dom);
document.selection.createRange().pasteHTML(wrap.innerHTML);
}
pt.insertDom = function(dom){
//光标处插入非元素
if(window.getSelection){
this.insertDomForStandard(dom);
}else{
this.insertDomForIe(dom);
}
}
pt.getContent = function(){
//获取数据
var nodes = this.dom.childNodes;
var datas = [];
for(var index = 0; index < nodes.length; index ++){
var node = nodes[index];
if(node.nodeType == 3){
datas.push(node.textContent || node.nodeValue || node.data);
}else{
datas.push(node.getAttribute('data-id'));
}
}
return datas.join('##');
}
主要内容:
- range(选区):IE与标准浏览器的兼容性,值得注意的IE操控选区时,需要让被操控元素(也就是选区所在的元素)获取焦点,否则会失败。
- 标准浏览器range的APi可参考此地址:http://www.w3school.com.cn/xmldom/dom_range.asp
- 获取数(getContent):将html结构的数据转换为标准的数据,防止脚本攻击。
3. LeaveMsg类(留言板管理类)
var LeaveMsg = function(opts){
this.opts = opts;
this.createFaceWrap();
this.createUitls();
this.curLocation;
}
var leaveMsgPt = LeaveMsg.prototype;
leaveMsgPt._insertFace = function(id){
var img = document.createElement('img');
img.setAttribute('class','face-img');
img.setAttribute('data-id', id);
img.src= '../img/face/' + id + '.jpg';
this.selectionUitls.insertDom(img);
this.faceWrap.hide();
}
leaveMsgPt.createFaceWrap = function(){
var self = this;
var faceOpt = {
onChooseImg:function(evt){
//插入表情,获取位置,获取表情,插入表情
var id = (evt.target||evt.srcElement).getAttribute('data-id');
self._insertFace(id);
}
}
this.faceWrap = new FaceWrap(this.opts.faceHead, this.opts.faceCont, faceOpt);
}
leaveMsgPt.createUitls = function(){
this.selectionUitls = new SelectionUitls(this.opts.area);
}
leaveMsgPt.getContent = function(evt){
this.selectionUitls.getContent();
}
实现FaceWrap、SelectionUitls类与LeaveMsg类的组合,并对UI提供相就的API。
四、使用他们
js部分代码
var leaveMsgArea = document.getElementById('leaveMsgArea');
var faceHead = document.getElementById('head');
var faceCont = document.getElementById('cont');
var leaveMsg = new LeaveMsg({
area: leaveMsgArea,
faceHead: faceHead,
faceCont: faceCont
});
HTML部分代码
<div class="leaveMsgArea" contenteditable="true" id="leaveMsgArea">
</div>
<div class="face-wrap">
<a class="face-head" id="head" href="javascript:void(0)">表情</a>
<div class="face-cont" id="cont">
</div>
</div>
<div class="button-group">
<button type="button" onclick="leaveMsg.getContent(event)" >获取内容</button>
</div>
- Docker Compose version 3 使用详解
- Virtualbox 安装 Alpine Linux
- LinuxKit 使用
- Docker 实践遇到的问题(持续更新)
- GitHub Pages 常见问题
- SpyDealer深度剖析:一个广泛针对中国手机APP进行信息窃取的恶意软件
- Docker + Drone CI/CD 实践
- Petya及Notpetya的核心差异分析
- macOS aria2 命令行使用详解
- 看我如何破解OpenNMS哈希密码?
- Fish Shell 命令补全
- 2017年最适用于WIFI HACK的无线网卡推荐
- OpenSSL 加密解密文件
- Docker 清理命令 prune
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 详解kubeadm安装k8s集群常见问题
- Python 3.7 + Django 2.2.5 Web项目搭建
- Flink集成数据湖之实时数据写入iceberg
- unittest简单应用
- 假如 Web 当初不支持动态化
- Spring Boot使用OpenAPI规范
- 图论-单源最短路径(Dijskal算法)
- Mysql系列第二十五讲 mysql如何确保数据不丢失?有几点值得我们借鉴
- 使用Jsch进行安全的文件上传及下载
- 你见过最烂的代码长什么样子?
- 集智智能课程表项目 实战指南
- ZeroLogon(CVE-2020-1472) 分析与狩猎
- 什么是数字资产?
- 我要偷偷的学Python,然后惊呆所有人(第一天)
- Python 中的上下文管理