【原创】【1】rich editor系列教程。前期准备,兼容
【1】前期准备,兼容
索引目录:http://www.cnblogs.com/henryli/p/3439642.html
rich editor的原理无非是启用iframe的编辑模式或者div的contenteditable=true。然后使用document.execcommand来编辑选取文本。但会使用到selection操作和range。
查看api: msdn地址,mozilla富文本编辑指引。w3school range。
使用iframe作为编辑器的优势:独立的编辑document、不会与页面其他选择冲突,独立的redo undo操作。缺点,如果页面设置了document.domain,而编辑模式中的js无法执行,会造成权限错误,有加载失败的可能。
使用div作为编辑器,轻量、加载不会失败、效率提升。但不适用于重量级、多功能文本处理,同时selection、range、undo的与页面元素共有。
ie使用了跟w3c不一样的api,返回的结果类似,不兼容。
创建range对象:
var selection = ifrDoc.createRange ? ifrDoc.createRange() : ifrWin.getSelection();
var range = selection.createRange ? selection.createRange() : selection.getRangeAt(0)
编辑器的基本原理不做叙述,这方面的博文很多,google一下即可
同样,不同的浏览器对于回车按键的处理也不一致,ie浏览器会产生一个成对儿的<p></p>标签,chrome为<div></div>,firefox根据版本为p或者br。
如何解决这个问题?将所有的换行设置为段落,或者设置为br
firefox,使用命令insertBrOnReturn命令,最后参数为true,会产生br,为false则产生p标签
document.execCommand("insertBrOnReturn",false,'true');
ie,默认的,产生成对的段落p标签(chrome为div标签,but,如果chrome中编辑器默认的元素为<p></p>,那么我大chrome则智能的把换行段落tag设置成了<p>) , 搜噶。。。统一为段落的p标签,就是这么easy。(firefix设置:document.execCommand("insertBrOnReturn",false,'false');ie是默认,chrome设置初始p tag)
ps: 编辑器默认必须有html,ie可以为空,其他浏览器至少要有br元素,否则会出现focus无光标的问题。同样,如果用户设置了初始html,同时换行为段落P的tag,那么此时就需要给html内容套上一个p容器。同样,保证p标签内部不允许有p元素,如果有,则要产生新的段落,这部分,可以封装在一个 empty() 的方法。
//当换行为br
editor.innerHTML = Util.msie ? '' : '<br />';
//当换行为段落
editor.innerHTML = '<p>' + (Util.msie ? '' : '<br />') + '</p>';
多数情况,设置为p标签,是最符合文章的编辑,毕竟,enter换行产生新的段落是那么的“语义”,哈哈。 但总有需要,换行需要设置为br。那么问题来了。firefox可以使用编辑器命令设置为br,其他浏览器,需要绑定事件,在按下回车的时候,删除当前选区的内容,插入一个<br/> 的代码,同时设置光标选中空格,删除它,因为插入空格再文档末尾不可用。
代码:
if (e.keyCode == 13 && self._bindEnter == true) {
e.preventDefault ? e.preventDefault() : e.returnValue = false;
//如果insertHTML命令失败,手动添加br
var range = self.getRange().range;
self.insertHTML(range.pasteHTML ? '<br/>' : '<br/> ');//不添加空格,在末尾无法有时候无法执行br
if (!range.pasteHTML) {
//chrome\ie9\ie19
var rangeData = self.getRange();
var range = rangeData.range;
range.setStart(range.startContainer, range.startOffset - 1);
var _selection = self.getRange().selection;
_selection.removeAllRanges();
_selection.addRange(range);
document.execCommand("Delete", false, null);
}
}
为了方便,会添加个insertHTML的方法,插入br、tab占位等,低版本的ie浏览器,直接使用range.pasteHTML即可,反之使用execCommand的insertHTML,如果命令失败,调用range.createContextualFragment,创建文档片段,range.insertNode,插入字符串html,最终再设置位置、添加到selection中,
发现bug,ie9移除了低版本的pasteHTML,但又未支持w3c的createContextualFragment方法,只好使用createDocumentFragment方法来创建文档碎片。
代码:
execCommand: function(type, value) {
var result;
try {
//当ie调用无法执行的命令会报错
result = this.ifrDoc.execCommand(type, false, value);
} catch (e) {
}
this._console('execCommand', type, value, 'result:' + (result ? 'ok' : 'false'));
return result;
},
insertHTML: function(html, fn) {
var self = this;
if (!self.execCommand("insertHTML", html)) {
//ie不支持insertHTML
var rangeData = self.getRange();
var range = rangeData.range;
if (document.selection && range.pasteHTML) {
range.pasteHTML(html);//早期ie的方法
range.collapse(false);
} else {
range.deleteContents();//删除选择的内容.
//#bug ie9去除了pasteHTML,却没有createContextualFragment方法,ie10已添加
var rangeNode;
if (range.createContextualFragment) {
rangeNode = range.createContextualFragment(html)
} else {
rangeNode = document.createDocumentFragment();
var div = document.createElement("div");
rangeNode.appendChild(div);
div.outerHTML = html;
div = null;
}
range.insertNode(rangeNode);
range.collapse(false);
}
}
}
最后奉上demo,虽然是rich editor教程,但第一篇是不包含任何针对文字的格式设置的编辑器,我们是在做准备工作,哼哼。阅读api是少不了滴. 同样添加了n多工具方法。
update @2013-11-27 12:55:14
BY henry
mail : liyaohui.henry@gmail.com
【原创】【1】rich editor系列教程。前期准备,兼容的更多相关文章
- 【原创】【2】rich editor系列教程。了解document.execommand操作,保存丢失的range,实时反馈样式给工具栏
[原创][2]rich editor系列教程.了解document.execommand操作,保存丢失的range,实时反馈样式给工具栏 索引目录:http://www.cnblogs.com/hen ...
- [原创]K8_Delphi源码免杀系列教程
[原创]K8_Delphi源码免杀系列教程[2014] 虽是2014年的,但免杀思路方法并未过时 比如函数动态调用\代码注释法等至今依然有效 链接:https://pan.baidu.com/s/1H ...
- Android Studio系列教程四--Gradle基础
Android Studio系列教程四--Gradle基础 2014 年 12 月 18 日 DevTools 本文为个人原创,欢迎转载,但请务必在明显位置注明出处!http://stormzhang ...
- Android Studio系列教程三--快捷键
Android Studio系列教程三--快捷键 2014 年 12 月 09 日 DevTools 本文为个人原创,欢迎转载,但请务必在明显位置注明出处!http://stormzhang.com/ ...
- Spring Boot 2.x 系列教程:WebFlux 系列教程大纲(一)
摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! WebFlux 系列教程大纲 一.背景 大家都知道,Sprin ...
- CRL快速开发框架系列教程十三(嵌套查询)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- C#微信公众号开发系列教程三(消息体签名及加解密)
http://www.cnblogs.com/zskbll/p/4139039.html C#微信公众号开发系列教程一(调试环境部署) C#微信公众号开发系列教程一(调试环境部署续:vs远程调试) C ...
- C#微信公众号开发系列教程二(新手接入指南)
http://www.cnblogs.com/zskbll/p/4093954.html 此系列前面已经更新了两篇博文了,都是微信开发的前期准备工作,现在切入正题,本篇讲解新手接入的步骤与方法,大神可 ...
- C#微信公众号开发系列教程四(接收普通消息)
微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南) C#微信公众号开发系列教程三(消息体签名及加解密) C ...
随机推荐
- 利用 Intel Realsense做SLAM开发(一)
最近手里拿到一台Realsense D435,就是这个: https://click.intel.com/intelr-realsensetm-depth-camera-d435.html 所以准备拿 ...
- 第五章Web应用与应用层协议
Web应用与应用层协议 本篇博文中的主要参考文献是<计算机网络高级教程>,分别是吴功宜老先生和吴英教授合著.这部教程是我研究生老师所推荐的网络必读科目,由于该教程讲解的基础知识详细,但内容 ...
- JY播放器【QQ音乐破解下载】
今天给大家带来一款神器----JY播放器.可以直接下载QQ音乐的歌曲. 目前已经支持平台(蜻蜓FM.喜马拉雅FM.网易云音乐.QQ音乐) 使用方法: 在网页打开QQ音乐网站找到你要听的歌曲或歌单.复制 ...
- 修改Config文件
/// <summary> /// Config文件操作 /// </summary> public class Config { /// <summary> // ...
- TCP/IP三次握手四次挥手分析
流程图 全部11种状态 客户端独有的:(1)SYN_SENT (2)FIN_WAIT1 (3)FIN_WAIT2 (4)CLOSING (5)TIME_WAIT 服务器独有的:(1)LISTEN (2 ...
- HWI的安装
一.安装的过程 hwi的安装过程: 1.解压src源码包:tar -zvxf apache-hive-1.2.2-src.tar.gz 2.进到HWI目录下:cd /home/bigdata/apac ...
- nginx main函数
源代码: int ngx_cdecl main(int argc, char *const *argv) { ngx_int_t i; ngx_log_t *log; ngx_cycle_t *cyc ...
- Linux内核学习笔记(6)-- 进程优先级详解(prio、static_prio、normal_prio、rt_priority)
Linux 中采用了两种不同的优先级范围,一种是 nice 值,一种是实时优先级.在上一篇粗略的说了一下 nice 值和实时优先级,仍有不少疑问,本文来详细说明一下进程优先级.linux 内核版本为 ...
- 洛谷【P1057】传球游戏
https://www.luogu.org/problemnew/show/P1057 题目描述 在体育课上, 老师带着同学们一起做传球游戏. 游戏规则是这样的: n 个同学站成一个圆圈, 其中的一个 ...
- IT视频课程集
马哥Linux培训视频课程:http://pan.baidu.com/s/1pJwk7dp Oracle.大数据系列课程:http://pan.baidu.com/s/1bnng3yZ 天善智能BI培 ...