zoukankan      html  css  js  c++  java
  • 【原创】【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对象:

          

    1 var selection = ifrDoc.createRange ? ifrDoc.createRange() : ifrWin.getSelection();
    2 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() 的方法。

    1 //当换行为br
    2 editor.innerHTML = Util.msie ? '' : '<br />';
    3 //当换行为段落
    4 editor.innerHTML = '<p>' + (Util.msie ? '' : '<br />') + '</p>';

      

    多数情况,设置为p标签,是最符合文章的编辑,毕竟,enter换行产生新的段落是那么的“语义”,哈哈。   但总有需要,换行需要设置为br。那么问题来了。firefox可以使用编辑器命令设置为br,其他浏览器,需要绑定事件,在按下回车的时候,删除当前选区的内容,插入一个<br/>&nbsp;的代码,同时设置光标选中空格,删除它,因为插入空格再文档末尾不可用。

    代码:

    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/>&nbsp;');//不添加空格,在末尾无法有时候无法执行br
        if (!range.pasteHTML) {
            //chromeie9ie19
            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方法来创建文档碎片。

    代码:

     1 execCommand: function(type, value) {
     2     var result;
     3     try {
     4         //当ie调用无法执行的命令会报错
     5         result = this.ifrDoc.execCommand(type, false, value);
     6     } catch (e) {
     7     }
     8     this._console('execCommand', type, value, 'result:' + (result ? 'ok' : 'false'));
     9     return result;
    10 },
    11 insertHTML: function(html, fn) {
    12     var self = this;
    13     if (!self.execCommand("insertHTML", html)) {
    14         //ie不支持insertHTML
    15         var rangeData = self.getRange();
    16         var range = rangeData.range;
    17         if (document.selection && range.pasteHTML) {
    18             range.pasteHTML(html);//早期ie的方法
    19             range.collapse(false);
    20         } else {
    21             range.deleteContents();//删除选择的内容.
    22             //#bug  ie9去除了pasteHTML,却没有createContextualFragment方法,ie10已添加
    23             var rangeNode;
    24             if (range.createContextualFragment) {
    25                 rangeNode = range.createContextualFragment(html)
    26             } else {
    27                 rangeNode = document.createDocumentFragment();
    28                 var div = document.createElement("div");
    29                 rangeNode.appendChild(div);
    30                 div.outerHTML = html;
    31                 div = null;
    32             }
    33             range.insertNode(rangeNode);
    34             range.collapse(false);
    35         }
    36 
    37     }
    38 }
    View Code

    最后奉上demo,虽然是rich editor教程,但第一篇是不包含任何针对文字的格式设置的编辑器,我们是在做准备工作,哼哼。阅读api是少不了滴. 同样添加了n多工具方法。

    点我下载demo

    update @2013-11-27 12:55:14

    BY henry

    mail : liyaohui.henry@gmail.com

      

  • 相关阅读:
    spring-boot快速搭建解析
    springmvc处理ajax跨域
    Spring-AOP解析
    springmvc注解
    springmvc源码分析
    Spring源码分析
    JAVA性能优化
    数据取舍
    命令行控制
    Junit常用操作
  • 原文地址:https://www.cnblogs.com/henryli/p/3439640.html
Copyright © 2011-2022 走看看