【原创】【2】rich editor系列教程。了解document.execommand操作,保存丢失的range,实时反馈样式给工具栏
【原创】【2】rich editor系列教程。了解document.execommand操作,保存丢失的range,实时反馈样式给工具栏
索引目录:http://www.cnblogs.com/henryli/p/3439642.html
浏览器提供了document.execommand的一系列命令来实现文本、格式、插入等操作,当然,浏览器厂商支持不一致、或者跟预想结果不一样。导致了前端coder需要耗费更大的精力去实现一个兼容、统一的富文本编辑。
使用较多的浏览器api:
- execCommand ,设置格式样式等命令
- queryCommandState,查询命令返回结果。ps(根据这个,可以实现当前选区格式的实时反馈)
- queryCommandEnabled,返回布尔值,查询execCommand 命令是否可用,也就是是否可以成功执行当前命令
- queryCommandSupported 返回表明当前命令是否在当前区域上支持的 Boolean 值。
execCommand 命令总共有这些:
var CommandList = ["2D-Position", "absolutePosition", "backColor", "blockDirLTR", "blockDirRTL", "bold", "browseMode", "clearAuthenticationCache", "contentReadOnly", "copy", "createBookmark", "createLink", "cut", "decreaseFontSize", "delete", "dirLTR", "dirRTL", "editMode", "fontName", "fontSize", "foreColor", "formatBlock", "enableInlineTableEditing", "enableObjectResizing", "forwardDelete", "heading", "increaseFontSize", "indent", "inlineDirLTR", "inlineDirRTL", "insertButton", "insertFieldset", "insertIFrame", "insertInputButton", "insertInputCheckbox", "insertInputFileUpload", "insertInputHidden", "insertInputImage", "insertInputPassword", "insertInputRadio", "insertInputReset", "insertInputSubmit", "insertInputText", "insertMarquee", "insertBrOnReturn", "insertHorizontalRule", "insertImage", "insertHTML", "insertLineBreak", "insertOrderedList", "insertUnorderedList", "insertParagraph", "insertSelectDropdown", "insertSelectListbox", "insertTextArea", "insertText", "italic", "justifyCenter", "justifyLeft", "justifyRight", "justifyFull", "justifyNone", "liveResize", "multipleSelection", "open", "overWrite", "outdent", "paste", "playImage", "print", "redo", "removeFormat", "refresh", "removeParaFormat", "selectAll", "saveAs", "sizeToControl", "sizeToControlHeight", "sizeToControlWidth", "stop", "stopImage", "strikeThrough", "subscript", "superscript", "unBookmark", "underline", "undo", "unlink", "useCSS", "hiliteColor", "unselect", "styleWithCSS"]
其中有上一篇用到的insertBrOnReturn和insertHTML。有了命令列表我们可以做一个测试页,测试命令是否受浏览器支持。当然其中还是一部分是暂时还没有任何浏览器支持的,rich editor也只用到其中的一部分命令。
命令styleWithCSS,设置为true,如果浏览器支持,则改变格式使用表情的行内元素设置,反之使用b、i、u、font等标签设置,对于富文本来说,自然是使用标签来设置,行内样式权重过大,也不“语义”。
设置文本、段落格式、样式需要用到:bold、italic、underline、strikethrough、superscript、subscript、removeformat、forecolor、backcolor、fontfamily、fontsize、justifyleft、justifycenter、justifyright、indent、outdent
链接相关:createlink、unlink
插入设置内容:insertorderedlist、insertunorderedlist、insertImage、insertHTML、insertText
常用操作: selectAll、redo、undo、paste、print、copy
其中有些命令与我们预期的不一样:
- fontsize,预期可以设置px、em文本大小,但浏览器却统一口径,只给了<font size="[0-7]"></font>,font未来要被废弃,而且无法设置自定义大小,需求兼容修正
- undo、redo,如果是使用iframe作为编辑器,iframe的document的undo、redo是“完整的”,如果是div,那么将与页面的操作重叠,需要定制一套undo、redo功能
- 待续
当鼠标选择了编辑器以外的内容,这时候选择已经丢失了,使用插入图片、文本格式,如何保证操作的是编辑器的最后选择的选区呢?
ie总是考虑的更加完善,给开发者提供了很好的api。提供了bookmark的功能;同时,ie提供了onbeforedeactivate和onactivate,来监听blur之前、focus之前的操作,在这个时间段,来获取书签和设置选区的书签最好不过了
支持标准selection、range的浏览器就稍微麻烦了,需要我们把光标更改的时候,保存range到变量中,在需要的时候,设置回来。chrome跟ie 本身就支持document.onselectionchange,首选由ie支持的,绑定此方法,就可以监听选区改变了,
//ie绑定获取书签,设置书签方法
if ('onbeforedeactivate' in ifrWinOrEditor && document.selection) {
var ieRangeBookMark;
ifrWinOrEditor.attachEvent('onbeforedeactivate', function() {
doc.selection.getBookmark();
});
ifrWinOrEditor.attachEvent('onactivate', function() {
doc.selection.moveToBookmark(ieRangeBookMark);
});
} else {
//反之当选区更改的时候保存range
self._console('bind selectionchange');
if ('onselectionchange' in doc) {
Utils.bind(doc, 'selectionchange', function() {
self.saveRange();
});
} else {
Utils.bind(doc, 'mouseup', function() {
self.saveRange();
});
Utils.bind(doc, 'keyup', function(e) {
self.saveRange();
});
}
}
saveLastRange: function() {
this.getRange() && (this.lastRange = this.getRange().range);
},
setLastRange: function() {
if (this.lastRange && this.getRange()) {
var selection = this.getRange().selection;
if (selection.removeAllRanges) {
selection.removeAllRanges();
selection.addRange(this.lastRange);
}
}
}
最终还需要判断当前的selection是否在编辑器中,因为当div作为编辑器,此时的选区可能在页面其他地方。ie支持Element.contains来判断是否包含某元素,而w3c使用compareDocumentPosition来判断,判断的代码直接放在getRange中,这样非编辑器中的选区,返回的是null。代码如下:
//如果是div编辑器,要判断range是否在编辑器中
if (this.editor != node) {
var isChild;
if (this.editor.contains) {
isChild = this.editor.contains(node);
} else {
isChild = this.editor.compareDocumentPosition(node) == 20;
}
if (!isChild) {
range = text = selection = null;
}
}
demo已完成;点击下载
预览图:
update @ 2013-11-25 15:37:11
BY henry
mail : liyaohui.henry@gmail.com
【原创】【2】rich editor系列教程。了解document.execommand操作,保存丢失的range,实时反馈样式给工具栏的更多相关文章
- 【原创】【1】rich editor系列教程。前期准备,兼容
[1]前期准备,兼容 索引目录:http://www.cnblogs.com/henryli/p/3439642.html rich editor的原理无非是启用iframe的编辑模式或者div的co ...
- SpringBoot系列教程JPA之指定id保存
原文链接: 191119-SpringBoot系列教程JPA之指定id保存 前几天有位小伙伴问了一个很有意思的问题,使用 JPA 保存数据时,即便我指定了主键 id,但是新插入的数据主键却是 mysq ...
- Influx Sql系列教程二:retention policy 保存策略
retention policy这个东西相比较于传统的关系型数据库(比如mysql)而言,是一个比较新的东西,在将表之前,有必要来看一下保存策略有什么用,以及可以怎么用 I. 基本操作 1. 创建re ...
- 【原创】【目录】实现rich editor(富文本编辑器)教程,深入理解selectiona/range操作与浏览器差异
日常工作中,接触富文本编辑的次数还是很多,特发此教程,希望可以改变富文本编辑的技术门槛较高的现状,解决这部分的坑. 前提准备,兼容获取range,统一回车行为,前期准备工作 了解document.ex ...
- SpringBoot 系列教程 JPA 错误姿势之环境配置问题
191218-SpringBoot 系列教程 JPA 错误姿势之环境配置问题 又回到 jpa 的教程上了,这一篇源于某个简单的项目需要读写 db,本想着直接使用 jpa 会比较简单,然而悲催的是实际开 ...
- Influx Sql系列教程九:query数据查询基本篇二
前面一篇介绍了influxdb中基本的查询操作,在结尾处提到了如果我们希望对查询的结果进行分组,排序,分页时,应该怎么操作,接下来我们看一下上面几个场景的支持 在开始本文之前,建议先阅读上篇博文: 1 ...
- Influx Sql系列教程八:query数据查询基本篇
前面几篇介绍了InfluxDB的添加,删除修改数据,接下来进入查询篇,掌握一定的SQL知识对于理解本篇博文有更好的帮助,下面在介绍查询的基础操作的同时,也会给出InfluxSql与SQL之间的一些差别 ...
- Influx Sql系列教程七:delete 删除数据
前面介绍了使用insert实现新增和修改记录的使用姿势,接下来我们看一下另外一个简单的使用方式,如何删除数据 1. delete 语句 delete的官方语法如下 DELETE FROM <me ...
- Influx Sql系列教程六:insert 修改数据
在influxdb中没有专门的修改数据的update语句,对于influxdb而言,如果想修改数据,还是得使用我们前面的说到的insert来实现,那么怎么判断一条insert语句是插入还是修改呢? 1 ...
随机推荐
- shell基础 -- 入门篇
shell 英文含义是“壳”,这是相对于内核来说的,shell 也确实就像是内核的壳,通常来说,所有对内核的访问都要经由 shell .同时,shell 还是一门功能强大的编程语言.shell 是 L ...
- 如何选择合适的Qt5版本?
注意:这里讨论的是在不编译Qt源码的情况下,推荐下载的官方编译版本. 支持XP SP3以及之后的Windows版本:推荐 Qt5.6 或 Qt5.9,这两个版本是LTS版本(即长期支持版本),Bug较 ...
- PHP中的数据类型
PHP中包含8种数据类型,其中包括4种标量:整型,浮点型,字符串,布尔值:2种复合类型:数组和对象:一种resource类型,剩下的一种是NULL类型. 整型 PHP中的整型可以是负,也可以是正,而整 ...
- HDU 5861 Road 线段树区间更新单点查询
题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=5861 Road Time Limit: 12000/6000 MS (Java/Othe ...
- HDU 5285 wyh2000 and pupil 判二分图+贪心
题目链接: hdu:http://acm.hdu.edu.cn/showproblem.php?pid=5285 bc:http://bestcoder.hdu.edu.cn/contests/con ...
- MDL
1 先是mdl的数据结构. 2 下面根据用法逐步的讲解mdl数据结构的含义:一般用法,先是 IoAllocateMdl :原型为: 最常用的是VirtualAddress和Length.把自己的Non ...
- SQL 语句(增删改查)
一.增:有4种方法1.使用insert插入单行数据: --语法:insert [into] <表名> [列名] values <列值> 例:insert into Strden ...
- 奇异值分解(SVD)原理详解及推导 (转载)
转载请声明出处http://blog.csdn.net/zhongkejingwang/article/details/43053513 在网上看到有很多文章介绍SVD的,讲的也都不错,但是感觉还是有 ...
- Java基于Tomcat Https keytool 自签证书
本文大部分内容系转载,原文地址:https://www.cnblogs.com/littleatp/p/5922362.html keytool 简介 keytool 是java 用于管理密钥和证书的 ...
- mac下面安装Navicat Premium 12.0.24 for mac已破解中文亲测可用
链接:https://pan.baidu.com/s/17HQ7dsCun2cSJGRpdP9yXA 密码:hwq5 Navicat_Premium_mac 最新版 12.0.24(原版是英文的) ...