• 一步步教你实现富本文编辑器(第二部分)


    这部分是利用iframe实现我们的富文本编辑器。上面提到激活编辑模式有两个方法,contentEditable="true"与designMode="On"。contentEditable 是针对单个元素,而designMode是面向整个文档的。因此,当我们使用iframe时,我们得先取到iframe的document。

    1.var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;

    不过,在这之前,我们首先动态生成iframe,然后再对iframe进行一些样式设置,插入到原textarea之前,既然有了iframe作为我们输入的场所,那么我们就没有必要留着textarea占着空间,我们把它隐藏便是。最后,我们用iframeDocument执行execCommand()就圆满了……下面是以上过程的代码

    01.   
    02.   //***********************************************************    
    03.    var textarea = document.getElementById("textarea");
    04.    textarea.style.display = "none";
    05.    var iframe = document.createElement("iframe");
    06.    iframe.style.width = "390px";
    07.    iframe.style.height = "100px";
    08.    iframe.frameBorder=0;
    09.    textarea.parentNode.insertBefore(iframe,textarea);
    10.    var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
    11.    iframeDocument.designMode = "on";
    12.    iframeDocument.open();
    13.    iframeDocument.write('<HTML><HEAD>');
    14.    iframeDocument.close();
    15.//***********************************************************

    嗯,基本上,所有常见游览器都能正常编辑文本了,除了FF有一个地方需要修正。在FF下,当我们试图改变文本的背影色时,发现整个iframe都变色了,原来FF的backcolor是针对文档的body元素的,要想和IE一致,我们需要用到hilitecolor,它才是针对我们选中的文本进行背景色设置。因此,修正如下:

    01.for(i=0,l=selects.length;i < l;i++){
    02.  selects[i].onchange = new function(){
    03.    var select = selects[i];
    04.    return function(){
    05.      var command = select.getAttribute("title"),
    06.      value = select.options[select.selectedIndex].value;
    07.      if(command == 'backcolor' && /a/[-1]=='a'){
    08.        iframeDocument.execCommand('hilitecolor',false,value);
    09.      }else{
    10.        iframeDocument.execCommand(command,false,value);
    11.      }
    12.    };
    13.  };
    14.};

    其中 /a/[-1]=='a' 是用来嗅探浏览器是否为FF。

    接着下来我们实现一下插入命令,如插件图片,插入表格等等。这个相对复杂些,我们还是可以利用execCommand命令,但对于表格,我们得另寻他法了!我们先实现一些相对简单的吧!

    修改表现层,增加命令按钮。

    01.   
    02.<div id="editor">
    03.  <!--         前略         //-->
    04.  <select title="backcolor">
    05.    <option style="color:#000000" value="#000000">■■</option>
    06.    <option style="color:#FF8080" value="#FF8080">■■</option>
    07.    <option style="color:#FFFF00" value="#FFFF00">■■</option>
    08.    <option style="color:#80FF00" value="#80FF00">■■</option>
    09.    <option style="color:#00FFFF" value="#00FFFF">■■</option>
    10.    <option style="color:#0000FF" value="#0000FF">■■</option>
    11.    <option style="color:#FF00FF" value="#FF00FF">■■</option>
    12.  </select>
    13.  <span class="button" title="createlink" unselectable="on">链接</span>
    14.  <span class="button" title="insertimage" unselectable="on">图片</span>
    15.</div>

    然后我们在点击这两个按钮时,弹出一个Promp窗口,让人们输入链接就是!

    01.for(var i = 0,l= buttons.length;i<l;i++){
    02.  buttons[i].onclick = new function(){
    03.    var command=buttons[i].getAttribute("title");
    04.    return function(){
    05.      if(command == 'createlink' || command == 'insertimage'){
    06.        var value = prompt('请输入超链接:', 'http://');
    07.        iframeDocument.execCommand(command,false,value);
    08.      }else{
    09.        iframeDocument.execCommand(command,false,'');
    10.      }
    11.    }
    12.  };
    13.};

    至于更复杂的插入,需要取得编辑光标的位置,这是个很麻烦的问题,我们留待pure DOM实现时才搞这个,现在我们试试提交内容。这个流程大抵是这个样子,当我们的iframe失去焦点(onblur)时,我们就偷偷把iframe里的内容拷贝到textarea中去,那么当我们提交时textarea里就有东西了!这看起来很简单,但当中的兼容问题会搞死一大班人!

    为了说明这个问题,我们做如下实验——

    1.iframe.onblur = function(){
    2.         //执行绑定事件
    3.}

    IE正常,其他游览器没反应,难道我们绑定事件的方式不对吗?!没办法,奠出我们的addEvent函数!

    嘿嘿,真是该死,W3C那帮家伙照旧没反应!遍历他们的iframe对象,发现它们是有blur与focus等方法,不过都是幌子,一个空实现!揭开谜底吧,在W3C标准中,iframe对象是不绑定任何事件,全部下放到其contentWindow中,并且以前onXXXX这样兼容写法也无效了,标准到底,我们要用标准的addEventListener函数才能请得动它!而要取得iframe的内容,其实就是取得其body的内容。

    1.var deliver = function(iframe){
    2.    addEvent(iframe.contentWindow,'blur',function(){
    3.        var tip = document.getElementById("exe");
    4.        iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
    5.        tip.innerHTML = "失去焦点,并取得iframe的内容为:"+iframeDocument.body.innerHTML
    6.        tip.style.backgroundColor = "#9999CC";
    7.    })
    8.}

    接着我们试图取得其编辑后的源码,也就是切换到HTML模式了。不用说HTML模式只能在textarea中显式,我们做一个按钮,用于隐藏与显示iframe与textarea就行了!

    01.   
    02.if(switchEditMode){//切换到textarea
    03.    iframe.style.display = "none";
    04.    textarea.style.display = "block";
    05.    textarea.value = iframeDocument.body.innerHTML;
    06.    textarea.focus();
    07.    switchEditMode = false;
    08.}else{//切换到iframe
    09.    iframe.style.display = "block";
    10.    textarea.style.display = "none";
    11.    iframeDocument.body.innerHTML = textarea.value;
    12.    iframe.contentWindow.focus();
    13.    switchEditMode = true;
    14.}

    好了,这部分就到此为止,下次我们将对它进行封装,并实现更为复杂的插入!

    根据 W3C标准click 方法只能赋予 input 元素。参考:http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-6043025
  • 相关阅读:
    es5预览本地文件、es6练习代码演示案例
    Java实现 LeetCode 838 推多米诺(暴力模拟)
    Java实现 LeetCode 838 推多米诺(暴力模拟)
    Java实现 LeetCode 838 推多米诺(暴力模拟)
    Java实现 LeetCode 837 新21点(DP)
    Java实现 LeetCode 837 新21点(DP)
    Java实现 LeetCode 837 新21点(DP)
    Java实现 LeetCode 836 矩形重叠(暴力)
    Subversion under Linux [Reprint]
    Subversion how[Reprint]
  • 原文地址:https://www.cnblogs.com/liufei88866/p/1537620.html
Copyright © 2020-2023  润新知