原文地址:http://aspalliance.com/1092_Rich_Text_Editor_Part_I
[原文×××]


开发一个自己的HTML在线编辑器(一)


摘要
在本文中,Haissam Abdul Malak将给大家详细介绍如何使用javascript开发一个HTML在线编辑器,它可以应用于web应用程序中,特别是论坛,社区和博客。这个编辑器支持基于XHTML创建文本的功能。


原文发布日期:2007.01.04
作者: Haissam Abdul Malak
翻译: webabcd


文章内容

介绍
我的一个朋友在一个正在开发的项目(一个博客网站)中遇到了一些问题,是关于文本编辑器的。在研究了所有免费的编辑器之后,他发现没有一个是他所需要的,所以我接下了这个任务,帮他开发一个HTML在线编辑器的用户控件,我认为和大家分享这个控件是个好主意,达到了知识共享的目的。

这个编辑器包括如下一些特性
1、工具栏包括了全部的功能(下面已列出)
    ·排列(居左,居中,居右)
    ·字体格式(加粗,下划线,斜体,字号,字体,文字颜色)
    ·计算单词数,删除格式,插入水平线,撤销,重复,插入字符

2、HTML模式结合到了一个框架中,文本模式结合到了另一个框架中。注意这两个框架只能有一个被显示。

3、有两个图标,分别是“HTML视图”和“设计模式”,一个文本框用来显示单词数,最后有两个隐藏文本框用来存储用户输入的数据。

要看懂这个实例,你需要有javascript和HTML的相关知识。


在用户控件中添加HTML代码
这部分我们将创建一个用户控件(hamHtmlEditor.ascx),并且在其中写一些必需的HTML代码。注意该用户控件不包含<head>, <body> 或 <form> 标记。

我们将创建3个表格来显示所有的图标,另外还要有3个下拉列表框。其中2个表格放在控件的顶端,1个表格放在控件的底部。每个图标都有3个事件,分别是onmouseover,onmouseup,onclick,处理这些事件的是javascript文件中的javascript代码。把javascript代码和HTML代码分开,可以让你更容易理解和调试。然后我们将创建3个层,第一个层包含一个已经有的HTML页(TextArea.htm)。我使用一个HTML页是因为如果用户输入了一个rul,它可以自动的把它转换为HTML代码并呈现在你的文本中。第二个层包括了1个textarea,在用户使用期间,它用来显示HTML代码(默认隐藏)。第3个层包含了一些符号,当用户点击“插入符号”后,这个层将被现实(默认隐藏)。

为了使用户能够输入文字,你必须在控件被使用的时候,将其设置为“设计模式”

列表1
οnlοad="document.frames['HamHtmlEditor1_content'].document.designMode='on'"

请下载这个项目以知道如何正确的创建所有的HTML标记
图1
 
javascript文件
这部分我们将写一些处理用户事件的函数。首先,我们将定义一些全局变量,其中每一个变量都有自己的功能,但最多的是用来存储图标在被单击之前或者默认的值—“No”。只有一个变量有另一个功能,这个变量是sourceText,它用来存储用户输入的文本。

列表2
var sourceText= '';
var imgStatusBold = 'No';
var imgStatusItalic = 'No';
var imgStatusUnderLine = 'No';
var imgStatusLeft = 'No';
var imgStatusCenter = 'No';
var imgStatusRight = 'No';
var imgStatusRemoveF= 'No';
var imgStatusWCount = 'No';
var imgStatusInsertL = 'No';
 
基于上面这些变量的值,当用户点击了1个图标,将检查相关的变量是否是“Yes”,它用来指明相关的图标并不是第一次加载时的图标。当用户控件全部加载完毕,我们将立即设置这些图标为他们的初始状态,当我们需要改变图标状态的时候,如果原来的值为“No”,就把它变为“Yes”。

有三个功能分别被称作onmouseover,onmouseup,和onclick。Onmouseover触发函数ChangeImg(),作用是当用户把鼠标放到图标上则改变所显示的图标的状态,这个函数需要两个参数(容器ID和新图标路径)。注意工具栏上的图标在web应用程序中被放置到“Images”文件夹下。

列表3
function ChangeImg(id, imgsrc)
{
         var imgSrc = "Images/" + imgsrc;
        document.getElementById(id).src = imgSrc;
}
 
Onmouseup函数的功能是用户的鼠标离开一个图标时,把这个图标该回其初始的状态,它需要3个参数(容器ID,新图标路径和1个变量)

列表4
function ReturnImg(id, imgsrc, ownVar)
{
         if(ownVar == 'No')
        {
                 var imgSrc = "Images/" + imgsrc;
                document.getElementById(id).src = imgSrc;
        }
}
第3个参数用来说明这个图标是否是被选中的状态,默认值是“No”。

单击图标后执行一个指定的动作,一个单独的javascript方法被调用,每一个动作都有标准的写法。

列表5
document.frames['HamHtmlEditor1_content'].document.execCommand('JustifyLeft', false, null);
 
使用上面这个方法可以使用户输入的文字居左。ExecCommand将在文档中执行一个命令。它使用一个预先组合到一起的功能来直接在浏览器中操作页面的布局。注意,只有在页面完全加载完毕后才能使用它。

列表6
function MakeBold(boldover, bold)
{
         var img = document.getElementById('Bold')                
         var imgBold = "Images/" + boldover
         var imgNotBold = "Images/" + bold
        img.src = imgBold;
                                    
         if(imgStatusBold == 'Yes')
        {
                imgStatusBold='No';
                img.src = "Images/" + bold;
        }
         else
        {
                imgStatusBold= 'Yes'
        }
        document.frames['HamHtmlEditor1_content'].document.execCommand('bold', false, null);
        document.frames['HamHtmlEditor1_content'].focus();                                
}
 
上面这段代码的功能是使用户输入的文字加粗的。当用户点击了加粗按钮,我们要改变这个按钮的状态。设置相关的全局变量为“Yes”,意思是该按钮已被选中。每次用户单击按钮,我们都要检查相关的变量,来确定之前按钮是否是被选中的状态,然后我们给选中的文字加粗。它需要两个参数,第一个用来存储鼠标经过时加粗按钮的图标路径,第二个用来存储正常加粗按钮的路径。相同的语法也在,斜体和下划线中适用。

对文字进行排列,我们使用与MakeBold()相似的函数,但是,3个排列功能的按钮只能有一个是被选中状态,其它两个要变为初始的未被选中的状态。

为了完成上面指出的那个execCommand命令,请参考
http://www.course.com/downloads/newperspectives/crweb3/documents/dhtml_t02.html

现在我们创建一个计算用户输入的单词数的函数。定义一个变量,默认值为0。在定义另一个变量用来存储用户输入的文本,我们将拆开这个变量,并且将拆开的结果保存到一个数组中,然后检查数组内每个元素的长度,如果是零则不计数,如果不是零则计数变量加1。计数完后,我们把该值赋给用于显示计数的文本框。

列表7
var wordCount = document.frames['HamHtmlEditor1_content'].document.body.innerText;
var count = 0;
countWithSpace = wordCount.replace('\n', '');
countWithoutSpaces = countWithSpace.split(' ');
for(i=0;i<countWithoutSpaces.length;i++)
{
         if(countWithoutSpaces[i].length>0)
        {
                count +=1;
        }
        window.parent.document.getElementById('HamHtmlEditor1_TxtCount').value = count;
}
 
当单击“删除格式”按钮后,我们调用一个javascript函数,发送命令“RemoveFormat”给execCommand用来删除选中文本的格式。

如果想删除某些已经有格式的文本的格式,这个功能将是非常有用的。

列表8
function RemoveFormating()
{            
        document.frames['HamHtmlEditor1_content'].document.execCommand('RemoveFormat');
        document.frames['HamHtmlEditor1_content'].focus();
}
 
“撤销”和“重做”功能与上面这段javascript类似。给execCommand发送“undo”或“redo”将执行撤销和重做功能。需要一个参数来指明命令的名字。

列表9
function Formats (style)
{
        document.frames['HamHtmlEditor1_content'].document.execCommand(style);
        document.frames['HamHtmlEditor1_content'].focus();
}
 
当用户单击“插入符号”按钮,我们将在该按钮之后显示第3个层来出示所有符号图片。我们使用javascript来做这件事。

列表10
function ShowDiv(p_w_picpaths)
{
         var div = document.getElementById(p_w_picpaths);
         if(div.style.display == 'block')
                div.style.display = 'none';
         else
                div.style.display = 'block';
}
 

图2:用户单击“插入符号”后,编辑器的外观
 
 
 
 
 
 
 
 
 
 
当用户点击第3个层的任意一个符号时,另一个javascript函数被调用,它用来在编辑器中指针的位置处插入符号。这个函数需要3个参数。第一个参数用来指定execCommand的命令来在文档中插入一个图片(InsertImage),第二个参数是图片的路径,第三个参数是该图片所在的层的id。注意所有的符号在web应用程序中被放置在一个“Emoticons”文件夹下。

列表11
function insertImages(style,url,p_w_picpaths)
{
        document.getElementById(p_w_picpaths).style.display = 'none'
        document.frames['HamHtmlEditor1_content'].focus();
        HamHtmlEditor1_content.document.execCommand(style,'',url)
        document.frames['HamHtmlEditor1_content'].focus();
}
 
当单击“HTML视图”按钮后,第二个层被显示,而第一个层则被隐藏。这个层的“readonly”属性被设置成了“true”,意思是用户在此状态下不能对其编辑,我们只能在这个层里看到HTML代码。

列表12
function TransformtoHtml()
{
        document.getElementById('HamHtmlEditor1_Div2').style.display = 'block';
        document.getElementById('HamHtmlEditor1_Div2').innerText =    
        document.frames['HamHtmlEditor1_content'].document.body.innerHTML;
}
 
当单击“设计模式”按钮后,第二个层则被隐藏

列表13
function TransformToText()
{
        document.getElementById('HamHtmlEditor1_Div2').style.display = 'none';
}
 
下拉列表用来让用户选择预先设定好的数据。

第一个是字号,尺寸在1(10pt)到7(22pt)之间。这个按钮被单击后,要调用一段javascript函数。这个函数获得用户在下拉列表里选择的值,然后作为第三个参数发送给execCommand。第一个参数是“FontSize”,用来执行设置文字大小的命令。注意,下拉列表中的字号大小是预先在用户控件中的HTML代码里定义好的。

列表14
function ChangeFont()
{
         var fontSize = document.getElementById('FontDropDownonchange');
        document.frames['HamHtmlEditor1_content'].document.execCommand('FontSize',0,fontSize.options[fontSize.selectedIndex].text);
        document.frames['HamHtmlEditor1_content'].focus();
}