在线所见即所得HTML编辑器的实现原理浅析


Posted in Javascript onApril 25, 2015

如今网站开发越来越提倡用户体验,为用户提供便利的工具也越来越多,而在线的HTML内容编辑器应该算是其中比较“古老”的一个了。功能简单的可以为用户提供文本的样式控制,例如文字的颜色、字体大小等;而功能复杂的甚至可以提供类似Word一样的强大功能。虽然现在各种开源的编辑器非常多,但是真正好用的并不多,所以它们改进工作也一直在进行中。

如今网上多数的编辑器都有很强大的功能,相对而言,在使用中也需要很多的配置,当然代码也自然会比较“臃肿”。如果我们并不需要功能那么强大的编辑器,那么可以自己实现一个,因为代码并不复杂。下面是一点个人的经验,仅供参考(以ExtJS的HTMLEditor为例)。

1、初始化。当页面加载完毕后,向页面添加一个IFrame(可选)。这里要注意的是,要判断页面的状态,要等页面完全加载完毕后再进行操作,防止出现找不到某些元素的错误。

2、打开编辑功能。将IFrame设为可以编辑(下面代码来自ExtJS的HTMLEditor):

// 获取iframe的window对象

getWin : function(){

        return Ext.isIE ? this.iframe.contentWindow : window.frames[this.iframe.name];

    },
//获取iframe的document对象

getDoc : function(){

        return Ext.isIE ? this.getWin().document : (this.iframe.contentDocument || this.getWin().document);

},
//打开document对象,向其写入初始化内容,以兼容FireFox

doc = this.getDoc();

doc.open();

doc.write('<html><head><mce:style type="text/css"><!--

body{border:0;margin:0;padding:3px;height:98%;cursor:text;}

--></mce:style><style type="text/css" mce_bogus="1">body{border:0;margin:0;padding:3px;height:98%;cursor:text;}</style></head><body></body></html>');

//打开document对象编辑模式

 doc.designMode = "on";

doc.close();

这样就可以向这个简单那的编辑器中写入内容了。
 
3、获取编辑器的内容,代码如下:

//获取编辑器的body对象

var body = doc.body || doc.documentElement;

//获取编辑器的内容

var content = body.innerHTML;

//对内容进行处理,例如替换其中的某些特殊字符等等

//Some code
//返回内容

return content;

 4、增加样式设置。上面的编辑器虽然实现了基本功能,但是实在是有些太简单了,应该增加些简单的样式实现。document的execCommand方法使这种想法成为可能。

//统一的执行命令方法

function execCmd(cmd, value){

    //doc对象的获取参照上面的代码

     //调用execCommand方法执行命令

    doc.execCommand(cmd, false, value === undefined ? null : value);

};
//将选中字体变为黑体,Ctrl-B

execCmd('bold');

//加下划线,Ctrl-U

execCmd('underline');

//变为斜体,Ctrl-I

execCmd('italic');

//设置文字的颜色

execCmd('forecolor', Ext.isSafari || Ext.isIE ? '#'+color : color);

//在光标处插入一段内容

function insertAtCursor(text){

  //win对象的获取参考上面的代码

  if(Ext.isIE){

      win.focus();

      var r = doc.selection.createRange();

      if(r){

        r.collapse(true);

        r.pasteHTML(text);      }

    }else if(Ext.isGecko || Ext.isOpera){

      win.focus();

      execCmd('InsertHTML', text);

    }else if(Ext.isSafari){

      execCmd('InsertText', text);

    }

  }

5、再进一步。如今可以改变样式了,如果编辑器有工具栏(这应该是必然的),那么我们还想工具栏上的按钮根据光标所处位置的样式,自动处于突出或正常显示。document的queryCommandState()方法又让这种想法得以实现。

//doc对象的获取参考上面的对面

//光标处是否是粗体

var isBold = doc.queryCommandState('bold');

if(isBold){

  //改变Bold按钮的样式

}

//当然上面的代码是可以合并的,这里只不过是一个示意


//下划线

doc.queryCommandState('underline');

//斜体

doc.queryCommandState('italic');

本文只是为实现编辑器提供了简单的思路,其中的一些代码是可以直接使用的。建议,想自己实现编辑器的朋友可以参考下ExtJS中的HTMLEditor代码,既简单又比较清晰,可以在其上进行扩展。

最后提醒一点:一定要注意浏览器的兼容性问题,并且不要等接近尾声了再去测试兼容性,对于这么大量的JavaScript代码,调整是比较痛苦的事情。

Javascript 相关文章推荐
jquery 元素相对定位代码
Oct 15 Javascript
php对mongodb的扩展(小试牛刀)
Nov 11 Javascript
jquery制作搜狐快站页面效果示例分享
Feb 21 Javascript
JavaSript中变量的作用域闭包的深入理解
May 12 Javascript
iScroll中事件点击触发两次解决方案
Mar 11 Javascript
jQuery数组处理函数整理
Aug 03 Javascript
Jquery和Js获得元素标签名称的方法总结
Oct 08 Javascript
node.js到底要不要加分号浅析
Jul 11 Javascript
详解Vue的常用指令v-if, v-for, v-show,v-else, v-bind, v-on
Oct 12 Javascript
使用vue自定义指令开发表单验证插件validate.js
May 23 Javascript
Webpack中SplitChunksPlugin 配置参数详解
Mar 24 Javascript
vue 解决无法对未定义的值,空值或基元值设置反应属性报错问题
Jul 31 Javascript
JavaScript在Android的WebView中parseInt函数转换不正确问题解决方法
Apr 25 #Javascript
Node.js和MongoDB实现简单日志分析系统
Apr 25 #Javascript
node.js操作mongodb学习小结
Apr 25 #Javascript
JavaScript按值删除数组元素的方法
Apr 24 #Javascript
JavaScript获取一个范围内日期的方法
Apr 24 #Javascript
jQuery中next方法用法实例
Apr 24 #Javascript
JavaScript实现多个重叠层点击切换效果的方法
Apr 24 #Javascript
You might like
php面向对象全攻略 (十七) 自动加载类
2009/09/30 PHP
Php Mssql操作简单封装支持存储过程
2009/12/11 PHP
PHP中替换换行符的几种方法小结
2012/10/15 PHP
PHP使用GIFEncoder类处理gif图片实例
2014/07/01 PHP
PHP输入输出流学习笔记
2015/05/12 PHP
windows下的WAMP环境搭建图文教程(推荐)
2017/07/27 PHP
js制作的鼠标悬浮时产生的下拉框效果
2012/10/27 Javascript
window.location.href = window.location.href 跳转无反应 a超链接onclick事件写法
2013/08/21 Javascript
解决css和js的{}与smarty定界符冲突问题的两种方法
2013/09/10 Javascript
JQuery结合CSS操作打印样式的方法
2013/12/24 Javascript
bootstrap模态框实现拖拽效果
2016/12/14 Javascript
Bootstrap提示框效果的实例代码
2017/07/12 Javascript
Angular搜索场景中使用rxjs的操作符处理思路
2018/05/30 Javascript
vue-cli 打包后提交到线上出现 &quot;Uncaught SyntaxError:Unexpected token&quot; 报错
2018/11/06 Javascript
vue cli 3.0 搭建项目的图文教程
2019/05/17 Javascript
[01:45]DOTA2众星出演!DSPL刀塔次级职业联赛宣传片
2014/11/21 DOTA
python3.4用函数操作mysql5.7数据库
2017/06/23 Python
解决pycharm界面不能显示中文的问题
2018/05/23 Python
解决tensorflow测试模型时NotFoundError错误的问题
2018/07/26 Python
Python多进程与服务器并发原理及用法实例分析
2018/08/21 Python
解决python中遇到字典里key值为None的情况,取不出来的问题
2018/10/17 Python
django框架使用方法详解
2019/07/18 Python
Python元组 tuple的概念与基本操作详解【定义、创建、访问、计数、推导式等】
2019/10/30 Python
在python中利用try..except来代替if..else的用法
2019/12/19 Python
django的403/404/500错误自定义页面的配置方式
2020/05/21 Python
css背景图片的背景裁切、背景透明度、背景变换等效果运用
2012/12/24 HTML / CSS
Canvas globalCompositeOperation
2018/12/18 HTML / CSS
NEW LOOK官网:英国时装零售巨头之一,快时尚品牌
2017/01/11 全球购物
介绍一下Ruby的多线程处理
2013/02/01 面试题
日语专业毕业生自荐信
2013/11/11 职场文书
大客户销售经理职责
2013/12/04 职场文书
开办饭店创业计划书
2013/12/28 职场文书
高中英语教学反思
2014/02/04 职场文书
公司领导班子对照材料
2014/08/18 职场文书
2014年幼儿园教师工作总结
2014/11/08 职场文书
党课主持词大全
2015/06/30 职场文书