以前也用过几个编辑器拉,如FCK,CUTEDTOR等,它们大都实现了很不错了的功能,也有丰富的插件使用。不过我还是觉得TinyMCE在线编辑器好用,它是采用纯JS客户端脚本技术构建,是一个轻量级加载速度非常快的WEB的文本编辑控件,并且TinyMCE是一个根据LGPL license发布的自由软件,你可以把它用于商业应用。

由于最进在做一个博客系统需要有在线编辑器,于是便找了TinyMCE在线编辑器,以前用过Google的GMail,里面就有一个按Ctrl+S的快捷键保存邮件的功能,因为当时还不太清楚那些编辑器的一些功能实现,对编辑器结构不清楚,也不知道用IE Developer Toolbar和Firebug等调试工具来看,所以那时候感觉Google特别牛B,而且Ctrl+S保存那个功能在FF里面运行,而FF浏览器按下Ctrl+S默认是弹出修改网页的对话框的,这让我更好奇了,难道JavaScript还能阻止浏览器里面Ctrl+S保存网页的快捷键,真的太神气了!下面我们就使用TinyMCE编辑器来实现一个按Ctrl+S使用Ajax异步保存文章的功能吧,这也是我的博客系统的需要。

在线编辑器的原理一般是创建一个ifrmae,这样便可相当于一个页面来进行单独控制,并且设置这个ifrmae的designMode="On"处于设置模式。TinyMCE是通过初使化配置一些参数,主要是传递一个textarea对象,并且在初始化的时候隐藏掉这些textarea,获取原来textarea的宽高在原来的新创建一个ifrmae对象。我们先用IE Developer Toolbar来看一下这个编辑器它创建的一些结构。

IEDeveloperToolbar

红色框标记的就是我们页面里面放置的textare文本输入控制了,这里是放的Asp.Net服务器控件,而绿色框里面标记的内容就是TinyMCE自动生成的东西了,可以看到这里面就是一个IFRAME,里面的BODY就是我们编辑器的内容了,它会自动初始话指定的textare的内容。这个IFRAsME的编号为我们指定的textare控件ID加上'_ifr',而且designMode="On"。所以我们要在线编辑器内按Ctrl+S实现保存就是要监听这个IFAME里面的事件了,关联到我们自定义的一个方法,可以是AJax请求服务器保存s,也可以执s行其他操作,那下面我就给出一个完成的DEMO。

上面所示就是一个完成的例子了,由于TinyMCE可以支持JavaScript,所以我就在编辑器里面用脚本再初始化一个编辑器,这个也是我博客里面所有的编辑器了,还有一些功能插件没能用上。我们先来看它的脚本是要如何来写的吧,先贴出它的代码:

<script type="text/javascript" src="/tiny_mce/tiny_mce.js"></script>
<script type="text/javascript">
    
var editorId = "txtContentEditor"
    tinyMCE.init({
        mode : 
"exact",
        elements : editorId,
        theme : 
"advanced",
        language : 
"zh",
    content_css : 
"/tiny_mce/css/content.css",    plugins : "safari,pagebreak,style,layer,table,advhr,advimage,advlink,emotions,iespell,inlinepopups,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template,insertCode,uploadImage",
        theme_advanced_buttons1:
"formatselect,fontselect,fontsizeselect,separator,forecolor,backcolor,separator,bold,italic,underline,strikethrough,separator,bullist,numlist,separator, justifyleft, justifycenter, justifyright",
        theme_advanced_buttons2:
"undo,redo,cut,copy,paste,separator,justifyleft,justifycenter,justifyright,separator,outdent,indent,removeformat,separator,link,unlink,image,uploadImage,media,separator,insertCode,separator,code,fullscreen",
        convert_fonts_to_spans:
true
    });
    
    addEvent(window,
"load",function (){
        setTimeout(
function (){
            
var content = tinyMCE.getInstanceById(editorId).getBody();
            
var editorDocument = document.all ? content : document.getElementById(editorId+"_ifr").contentDocument;
            addEvent( editorDocument ,
"keydown",function (e){editorKeyDown(e)});
        },
1000);
    });
    
    
function editorKeyDown(e)
    {
        
        
var num = e.which?e.which:e.keyCode;
        
if( e.ctrlKey && num == 83 )
        {
            
//postArticle();这里模拟Ajax保存文章
            InsertToEditor("<br />正在保存中。。。");
            setTimeout(
function (){
                InsertToEditor(
"<br />保存成功!!!");
            },
1000);
            
if (document.all)
            {
                
return false;
            }
else e.preventDefault();
        }
    }
    
    
function InsertToEditor(content)
    {
        tinyMCE.execCommand(
'mceInsertContent',false,content);  
    }
    
    
function addEvent(target,eventType,func){
        
if(target.attachEvent)
        {
            target.attachEvent(
"on"+eventType,func);
            
        }
else if(target.addEventListener)
        {
            target.addEventListener(eventType,func,
false);
        }
        
return this;
    }
</script>

TinyMCE.init这个方法不用说了,初始话textare编辑器,然后接着是addEvent方法,这个是后面定义的,之所单独出来是为了重用并兼容所有浏览器,这里需要注意的是FF内关联事件需要传递一个事件对象,而IE不需要传也可以直接获得,为兼容全部增加传递事件的参数,然后在再里面判断获取键盘按下的键,如果按下了Ctrl并同时按下了S(keyCode=83)则执行保存,这里是用setTimeout模拟Ajax请保存,这里说一下之所以监听keydown事件,那是因为在keydown、keypress 、keyup这三个事件里面keydown是最先触发的,而且也只能再这个事件里面阻止事件冒泡和默认行为(FF内),这个事件里面也是最能获取键盘按下键的最详细的信息,其他时间就不一定能获取得到(FF内),有时间再写一下JS事件的一些文章。接下来看下面keydown里面最关键的代码了,if(document.all) return false;这里是判断是否为IE内核的浏览器,不过正规的判断应该不是这样,这里为了简化就直接这样写了。return false是在IE里面阻止事件最的通用方法了,这里就不在撰述,后面一句是对非IE内核浏览器的处理。使用e.preventDefault()方法来阻止事件的默认行为,这个方法其实并是陌生,早在JQuery里面就有过介绍:

通过使用 preventDefault() 方法只取消默认的行为。在一些支持标准的DOM浏览器里,如果动态添加关联表单的submit的事件,只写return false是不行的,FF内仍然会submit,加上preventDefault()方法即可阻止表单提交。

jQuery 代码:

$("form").bind("submit", function(event){
  event.preventDefault();
});

通过使用preventDefault()方法取消事件默认行为,这个应该在所有支持WSC的DOM浏览器都可以,不过我还没有在safari 、opera 浏览器内做过测试,但至少在FF2.0和谷歌浏览器下执行没有问题。FF和谷歌浏览器在页面里面按Ctrl+S默认是弹出保存网页对话框,使用preventDefault()就能够阻止取消弹出对话框,是不是很神奇,呵呵^_^。因为这里浏览器里面事件的处理机智是先传递给网页再传递给浏览器,所以在网页里面就能通过JavaScript来阻止浏览器默认的事件了。不过需要注意的是FF好象关联body的事件无效,关联非text或textare可输入文本对象也无效,按Ctrl+S仍然是会谈出保存的网页的对话框,有点奇怪,好象Ctrl+S只是特别为text或textare预留的快捷键一样,最后还是通过关联框架的document对象contentDocument来搞定的。只要能关联到事件,又能取消按Ctrl+S默认行为,编辑器内按Ctrl+S就执行自定义的方法,我这里是使用AJax请求服务器保存编辑器内的内容,而且可以很友好的无刷新按Ctrl+S及时保存,这样不需要等到PostBack回服务器去,避免写文章到一般而没有即时保存而丢失的一些问题。

AjaxSaveArtcle Powered by: Jonllen

其他只要是IFRAME编辑器应该使用这种方法都可以实现按Ctrl+S自定义保存,不过写到最后面我告诉大家其实要显示Ctrl+S保存没必要这么复杂,因为TinyMCE在线编辑器里面提供了一个现成的save插件,我们园子里面就有用到。plugins :"safari,pagebreak,style,layer,table,save,advhr,advimage,advlink,emotions,iespell,inlinepopups,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template,insertCode,uploadImage",其中的save就是保存了,只要写指定有save在编辑器内按Ctrl+S就会自动Post回去,不过就是刷新了页面-_-。TinyMCE编辑器果然好用够人性化,连这种功能都预先想好提供了。不过我还是自己来实现了一次,下次碰到其他编辑器说不定也能用上,希望对大家有用。

本篇为作者Jonllen以"现状"提供,且没有任何担保,同时也没有授予任何权利。原文地址http://www.jonllen.com/Article.aspx?aid=16
posted on 2009-06-28 15:10  Jonllen Peng  阅读(1878)  评论(0编辑  收藏  举报