富文本编辑器&FileReader

最近在作一个web版的管理Tool,其中包括一个编辑框,要求可以编辑文字,插入图片,最后导出作成一个Html。对于资深人士看来,这很容易啊,不就是一个富文本编辑框吗?这其实就是一个概念的问题,对有经验的人来讲,脑子里面有了概念,就能一会儿抓到点上,快速地进行分析。可是对于我来讲就没有富文本编辑框的概念,加之因为公司内有作网页的比较少,可以求教的人很少,所以我只好一步一步慢慢研究,总之走了不少弯路。其中一些硌人的障碍就不说了。下面我就简短地总结一下有关经验吧。html


一.编辑框程序员

大多数富文本编辑框都是用iFrame作的。只要咱们将designMode属性设置成"on",则个iframe就具有了编辑功能。web

先写一个简单的框架:chrome

复制代码
<html>
<head>
</head>
<body>
    <textarea></textarea>
    <iframe id="iframe"></iframe>
  <sprint>
          createIframe:function(id){
              $ = this= document.getElementById("id");
              var doc =  $.contentDocument ||$.contentWindow.document; 
              doc.designMode = 'on';
              doc.open();
              doc.write('<html><head><style>body{ margin:3px; word-wrap:break-word; word-break: break-all; }</style></head><body>GoodNessEditor</body></html>');
              $.contentWindow.focus();
              doc.close();
          }
      windown.onload = functon(){
              refurn new createIframe("iframe");
          }
    </sprint>
</body>
</html>
复制代码

 从上面代码咱们能够得知,iframe的使用须要进行如下几个步骤:设计模式

1.要获取iframe的document文档。浏览器

var doc =  $.contentDocument ||$.contentWindow.document; 

2.将文档设成设计模式。即:将designMode属性设置成"on"。安全

3.打开文档(open),写入默认的document,关闭文档(close)。网络

  --固然也能够直接指定iframe的src来设定iframe的内容。app

ifram.src = "www.baidu.com";

 

二.工具栏框架

若是iframe是存放document的一个容器,那我会很好奇如何经过命令让容器里的document实现靠左、靠右、剪切、加粗、插入图片。这时就会用到execCommand命令。

通常execCommand都带有一下三个参数:

 

复制代码
execCommand(String aCommandName, Boolean aShowDefaultUI, String aValueArgument)

aCommandName  指令名称

aShowDefaultUI    是否使用默认UI

aValueArgument   具体命令(如是插入图片则输入url,若是插入文字则输入字符串)
复制代码

 

    由于我此次所作的编辑器很是简单,只用到了图片插入以及插入文字。因此只使用到两种命令:

图片插入
execCommand("insertimage",falser,url);
字符串插入
execCommand("InsertInputText ",falser,text);

知道这两种命令,接下来彷佛就比较简单了。只要取到相应的图片URL以及要插入的字符串,就能够执行命令。

但素,我是说但素,这两年程序员坐下来,我早已知道扣代码这种事,历来就没有可以让人省心的事。坑爹到处有啊你说是否是。

在执行这两个命令以前,咱们须要作两件事:

1.获取本地图片URL

2.获取本地文本中的字符串

 

3、FileReader读取本地资源

读取图片

我也翻找过很多网上使用较多的富文本编辑器,在导入图片这一项上,基本都是使用网络资源,而不是只用本地资源。若是要使用本地资源,读取本地图片的URL,所以就涉及到Html5的FileReader。

首先,咱们须要使用fileupload来选择图片:

复制代码
<input type="file" onchange="fileSelect(this.files)" />

<script>
    function fileSelect(files)(){
       var file = files[0],//由于能够选择多个文件,因此咱们只需选取头一件便可
             url;

       //判断文件是否存在
       if(file){
           if(file.tyoe.indexOf("image") < 0 ){
                //判断是否为图片
                alert("Please input image!");
                return ;
           }
           if (window.webkitURL.createObjectURL) {
            //Chrome8+
            src = window.webkitURL.createObjectURL(file);
          } else{//IE8+
              var reader = new FileReader();
              reader.onload = function(){
                  url = e.target.result;
              }
             reader.readAsDataURL(file);
           }
       }
    }
</script>
复制代码

上面咱们用到了两种图片读取方法。

一种是Html5原生的FileReader。可是这种方法是将图片读取成一个超长的二进制文件,若是图片过大,所生成的二进制文件也更大,对浏览器是一个承重的负担,所以不大建议使用。

固然FileReader不仅有一个方法,它有如下几个方法:

readAsBinaryString(file)   将文件读取为二进制码

readAsText(file,encode) 将文件读取为字符串

readAsDataURL(file)        将文件读取为DataURL

FileReader事件

onabort              ---------数据读取中断时触发
onerror              ---------数据读取出错时触发
onloadstart          --------数据读取开始时触发
onprocess            --------数据读取中
onload               --------数据读取成功完成时触发
onloadend            --------数据读取完成时触发,不管成功失败

FileReader属性

filereader.result        ---------读取结果

filereader.readystate    ---------读取状态(empty loading down)

 

另外一种读取方法是Chrome和safari为表明的webkit浏览器所拥有的图片文件读取方式:window.webkitURL.createObjectURL(file).

 --经过这种方法,将获得一个已编码过的相对路径,相比而言,体积大大减小。

 

读取到本地图片的URL后,我么就能够用execCommand指令将图片读入iframe中。

复制代码
<script>
    .......前略
    url = window.webkitURL.createObjectURL(file)
var iframe = document.getElementById("iframe");
var doc = iframe.contentDocument ||iframe.contentWindow.document;
doc.execCommand("insertimage",false,url);
iframe.contentWindow.focus(); </script>
复制代码

 

读取本地文本文件

一样咱们也能够用readerAsText来读取本地文件

复制代码
<script>
   function readText(files){
      var file = files[0];
      if (file) {
        
        var reader = new FileReader();
        var textResult;

        reader.onloadend = function (e) {
            textResult = e.target.result;
        }
        reader.readAsText(file, 'utf-8');
    }
   }

</script>
复制代码

 

本地文本字符串后,就能够用execCommand指令将字符串读入iframe中..................

<script>
  .....前略
     doc.execCommand( "insertinputtext" , false ,text);
     doc.designMode = "off" ;
     iframe.contentWindow.focus();
</script>

若是你是这么想的,那你就太天真了!!!!!!!!!!!

我测试了一下若是用execCommand("insertinputtext",false,text)指令,就可能回出现没法将读取的字符串插入iframe的状况,并且概率极高,插好多回都不必定能成功一次。后来想了一下,有多是这个指令须要遍历iframe中全部的节点,而后再body的最后一个节点插入字符串。这就致使该指令的执行效率很是之低。很坑爹是否是!!!!因此与其遍历全部节点,不如直接将字符串插入想要的节点中去。因而我就用到了如下方法。

<script>
  .......前略
  doc.getElementByTagName('body')[0].innerText = text;
</script>

如此一来,代码的执行效率就提升了。

 

4、保存HTML文件

这样一来,一个简单的富文本编辑器就算完成了,若是想增长其它功能,就请查找具体的execCommand命令。

可是,我还想再增长一个特殊的功能,就是将iframe的document文件保存到本地。

想固然的,确定也会想到使用execCommand指令中的"saveAs"指令。

可是很遗憾的告诉你,在一些好比chrome,FF上,saveAs指令是无效的。即使你使用它,也没法按照你的想象般弹出文件选择框出来。固然像IE之类的浏览器就不在咱们的讨论范围以内了。

我调查了一下为何chrome没法使用saveAs指令的缘由,是由于chrome为了提升浏览器的安全性,而禁止用JS将页面的文件保存到本地。

那么,既然用不了浏览器自身的API,那就只好另寻它径了。我不能保存,但我总能下载吧。

首先能够讲iframe的内容取出来。

复制代码
<script>
    var iframe = document.getElementById('RTE_iframe');
    var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
    var bodyHtml = "\n<body>" + iframeDocument.body.innerHTML + "</body>\n";
    var headHtml = "<head>" + iframeDocument.head.innerHTML + "</head>\n";
    var htmlFile = "<html>\n" + headHtml + bodyHtml + "</html>";
</script>
复制代码

以后就是要将这些东西下载到本地。

复制代码
<script>
  var BlobBuilder = BlobBuilder || WebKitBlobBuilder || MozBlobBuilder;
  var URL = URL || webkitURL || window;
  function saveAs(blob, filename) {
        var type = blob.type;
        var force_saveable_type = 'application/octet-stream';
        if (type && type != force_saveable_type) { // 强制下载,而非在浏览器中打开
            var slice = blob.slice || blob.webkitSlice || blob.mozSlice;
            blob = slice.call(blob, 0, blob.size, force_saveable_type);
        }

        var url = URL.createObjectURL(blob);
        var save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
        save_link.href = url;
        save_link.download = filename;

        var event = document.createEvent('MouseEvents');
        event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
        save_link.dispatchEvent(event);
        URL.revokeObjectURL(url);
    }

    var bb = new BlobBuilder;
    bb.append(htmlFile);
    saveAs(bb.getBlob('text/plain;charset=utf-8'), "test.html");
</script>
复制代码

这样,就可以将iframe中的内容保存到本地了。

相关文章
相关标签/搜索