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


    这部分是利用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
  • 相关阅读:
    Codeforces1070 2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Preferred)总结
    Codeforces 633H Fibonacci-ish II【线段树】
    一些Fibonacci数列的神奇性质【数学】
    Codeforces 620E New Year Tree【线段树傻逼题】
    Codeforces 828C String Reconstruction【并查集巧妙运用】
    Codeforces 559C Gerald and Giant Chess【组合数学】【DP】
    Codeforces 311B Cats Transport【斜率优化DP】
    BZOJ2933 [Poi1999]地图【区间DP】
    BZOJ3688 折线统计【树状数组优化DP】
    BZOJ2131 免费的馅饼【线段树优化DP】
  • 原文地址:https://www.cnblogs.com/liufei88866/p/1537620.html
Copyright © 2020-2023  润新知