您所在的位置: 程序员家园 -> 家园博客 ->
 
在哪里摔倒
就在哪里自己爬起来

用户登录

查  找

最新评论

最新留言

常用网站

网易邮箱 GMAIL  

百度搜索 MSDN

霏凡软件 BT精品

影视帝国 射 手 网

电驴下载 全 库 网

友情连接

茄菲的窝 冰冰博客

枫叶飘零 玫  瑰

ACEN 云 豹 子

统  计



在 Internet Explorer 5.5 中创建可编辑的 Web 页
狼子 发表于 2006-8-22 19:00:00 阅读全文 | 回复(0) | 引用通告 | 编辑

转自:http://www.microsoft.com/china/msdn/Archives/workshop/createwp.asp#createwp_topic1

Peggi Goodwin
Microsoft Corporation
2000年5月

摘要:本文讨论 MSHTML,这是对 Internet Explorer 中分析和展现引擎的 HTML 扩展,它允许直接在浏览器内编辑 Web 页。

目录


现在,您可以直接将 Microsoft(R) Internet Explorer 复杂的 HTML 编辑功能合并到 Web 页中!Microsoft 的 HTML 编辑器是对 Internet Explorer 中 HTML 分析和展现引擎的内置扩展。从 Internet Explorer 4.0 开始,MSHTML 编辑器已经为主机应用程序提供了开发基于 HTML 的文本编辑器和 Web 创作应用程序的 HTML 编辑平台。但是,在以前的版本中,只有当文档处在“设计”模式时,才能启用编辑器。使用 Internet Explorer 5.5,您可以将文档或文档中的单个元素声明为可以在运行时编辑,这就使得 Web 创作者能够完全支持浏览器内的 WYSIWYG(所见即所得)HTML 编辑权。

MSHTML 编辑器提供了简单而又功能强大的脚本编辑模式,该模式支持对文本和窗体的最常用的编辑功能。这样,就有可能开发出高级的联机编辑应用程序、创建允许用户输入格式化文本或图象等的统一窗体、或使 Web 站点上的页面成为每个用户都能用自己的内容对其定制。Web 创作者可能使用文本编辑功能来开发联机文本编辑器,或者使用窗体编辑功能来编写联机明信片应用程序。

文本编辑功能

下面的文本编辑功能已经在以前版本的 Internet Explorer 中得到支持,在 Internet Explorer 5.5 中同样支持这些功能。除键盘快捷键外(它们始终处于启用状态),所有这些功能都有可以在脚本中执行的对应命令。

剪切 (Ctrl + X) 复制 (Ctrl + C) 粘贴 (Ctrl + V)
粗体 (Ctrl + B) 斜体 (Ctrl + I) 下划线 (Ctrl + U)
撤消 (Ctrl + Z) 恢复 (Ctrl + Y) 超级链接 (Ctrl + K)
查找 (Ctrl + F) 全选 (Ctrl + A) 选定段落 (Ctrl + 单击左键)

Internet Explorer 5.5 中的新功能

当然,Internet Explorer 5.5 中最棒的新编辑功能之一,就是能够在浏览器运行时启用编辑功能,但我们将在后面讨论它。现在我们讨论 Internet Explorer 5.5 中其它一些新的和经过改进的功能,尤其是文本编辑:

垂直编辑是 Internet Explorer 5.5 中首次出现的功能。该功能主要针对那些使用中文或日文进行编辑的用户,但它在纯 ASCII 文本中也能很好地工作。使用西文字体的字符可以向右旋转,这样,在显示文本时仿佛整段文本都被顺时针旋转。Internet Explorer 5.5 中,双向文本支持也得到极大改进。该功能主要用于希伯来和阿拉伯的文本。虽然经常会有一些英文的单词和词组,或者其他基于拉丁文的单词或词组,被插入到希伯来和阿拉伯的文本中。在 Internet Explorer 5.5 中,当遇到拉丁文字符集时,主要的定位方向将自动切换为从左到右,而当检测到希伯来文或阿拉伯文字符集时又会自动切换为从右到左。

批撤消和恢复使用户可以立刻删除和还原整个句子,而不是一次一个字符。现在,如果由于某些原因用户不想让某个链接处于活动状态,则可以使用 BACKSPACE 键撤消自动检测到的链接。

在复制和粘贴文本时,该编辑器现在可以很好地保持格式。例如,如果复制了格式为粗体、红色宋体格式的文本,然后将它粘贴到格式为粗体 Times Roman 的文本段中,那么所粘贴的文本将保持其粗体、红色宋体格式。现在,格式还能在空行上保持。如果将某行的格式设置为 16 点、斜体、Haettenschweiler,并数次点击 RETURN,当您返回这些空行并在其中键入字符时,文本将以 16 点、斜体、Haettenschweiler 格式输入,而不再是文档的默认字体。

Web 创作功能

Internet Explorer 中的 HTML 编辑器一贯支持下面这些基本的 Web 创作功能,未来仍将继续支持。

控件、IFrames、图象、字幕、水平线和表格全都有一些共同之处。每个元素都有各自的布局。所谓具有布局,基本上表示着对象呈矩形。(实际上,只要为任何元素指定宽度和高度,或使它 contentEditable,就可以使它具有布局。)如果布局元素包含有内容,则其内容的布局是由界定其范围的矩形来决定。

可以与选择文本一样,按住鼠标左键并在其上拖动鼠标,就可以选定具有布局的元素。但是,当布局元素位于可编辑容器内部时,也可以通过单击或按 TAB 键对它进行控制选定。当元素被控制选定时,将在框定它的矩形角和每个边的中点上显示“抓取手柄”。当元素被控制选定时,可以将其作为单个单位拖动(或删除),连带它的所有内容。还可以用鼠标拖动它的抓取手柄来调整其大小。元素被控制选定时,单击它或点击 ENTER 键将使它成为被激活的 UI。当元素成为活动的 UI 时,(除非它是不能有内容的元素,如图象或水平线,)将在它的周围出现晕线边框,并且可以编辑它的内容。

Internet Explorer 5.5 中的新功能

Internet Explorer 5.5 拥有窗体编辑器的所有功能,此外,它还支持一些很棒的新功能,这些新功能使得创建窗体和 Web 页成为轻松并充满乐趣的工作。这些新功能包括:

使用 2D 绝对定位,用户只需进行拖放操作,就可以把元素放到页面的任何位置上。(再也不用创建以前那些复杂的表格,就可以得到希望的准确布局了!)

现场调整大小功能让用户在调整元素大小时获得现场的 WYSIWYG 反馈。用户不用在拖动鼠标的同时描绘外边框,并在松开鼠标按钮时让元素自行调整大小,元素将随着用户拖动它的抓取手柄实时地调整大小。

多项选定让用户能够一次选定多个元素,并同时拖动它们或调整其大小。

新的“不可选定”属性使您能够为 Web 页创建用户界面元素,它们不会在用户单击时使当前选定内容遭到破坏。这对创建更改当前选定内容格式的控件非常有用,这一点我们随后就会谈到。

激活编辑器

激活编辑器的方法有两种。第一种方法是将整个文档设置为设计模式。第二种方法可以在浏览模式中使用,来使各个元素可在运行时编辑。如果想让整个文档可在浏览时进行编辑,则可以在文档正文上设置 contentEditable 属性。

将文档设置为设计模式

要将整个文档设置为设计模式,可以对文档对象本身设置 designMode 属性。当文档处于设计模式时,将不运行脚本。这样,似乎在文档内设置一个按钮来打开或关闭设计模式是个好注意,但这样做没有作用。当用户打开它后,它将保持在设计模式状态。当他们下次单击此按钮时,它将被选定而不是被单击,他们再次单击它,将能够编辑它的值。这就是为什么如果要使用设计模式最好对框架或 IFrame 中的文档设置 designMode 属性的原因。下例展示如何为 IFrame 中的文档打开设计模式:

<script for="btnDesign" event="onclick">
  targetDoc = document.frames(0).document;
  if (targetDoc.designMode == "On")
    targetDoc.designMode = "Off";
  else
    targetDoc.designMode = "On";
</script>
<button id=btnDesign>DesignMode</button>
<iframe src="/blank.htm" style="border: black thin; width:100%; height:200px"></iframe> 

designMode 属性的值始终以首字母大写格式存储,即时它最初是以全部小写设置的。请在测试它的值时一定记住这点。designMode 属性的默认值是“Inherit”。

在浏览模式中使元素可以编辑(或在设计模式中不可编辑)

在 Internet Explorer 5.5 中,可以针对每个元素激活编辑器,而同时,文档本身处于浏览模式中。只要将 contentEditable 属性设置为 True,就能使元素在浏览时可被编辑。下例展示如何说明性地设置该属性,并创建行为类似文本框的跨距:

<span contentEditable=true style="width:150; border:lightgrey 3px inset"></span>

要使元素在全部脚本过程中可被编辑是非常容易实现的。下面的范例显示如何在脚本中对 ID 为“foo”的元素设置 contentEditable 属性:

foo.contentEditable=True;

要防止元素在设计模式中处于可编辑状态,可以将 contentEditable 属性设置为 False。但这将使元素具有布局,这样,当它在设计模式中时,用户将能够对它进行控制选定、拖动、调整大小等:

foo.contentEditable=False;

contentEditable 元素的继承和嵌套

contentEditable 属性是被继承的,所以,如果您说明元素具有 contentEditable 属性,则默认情况下它的所有子元素都将是可编辑的。(contentEditable 属性的默认值是“Inherit”。

通过将其 contentEditable 属性设置为 False,可以使 contentEditable 元素的后代成为不可编辑的,但这样之后,请记住设置元素的 contentEditable 属性将导致元素具有自己的布局。无论元素的 contentEditable 属性被设置为 True 或 False,都要发生这样的情况。还要记住,当有布局的元素处在可编辑的容器中时,一旦用户单击它的内部,它将被控制选定。当它被控制选定时,将显示抓取手柄,并且用户可以拖动该元素或调整其大小。这并不表示不应当在可编辑的元素内嵌套不可编辑的元素,只不过要加以注意罢了。

判断元素是否是可编辑的

要判断元素是否是可编辑的,只检查 contentEditable 属性的值是不够的。元素可能根本没有 contentEditable 属性,但仍然可能已经从它的某个祖先那里继承了内容可编辑性。或者,它可能是默认时可编辑的元素,如文本框。或者,包含它的文档可能处于设计模式中。确定元素是否可编辑的唯一完全可靠的方法是检查 isContentEditable 属性。isContentEditable 属性综合了所有这些因素。该属性是只读的,其结果为布尔值。下例展示如何判断 ID 为“foo”的元素是否可以被编辑:

result=foo.isContentEditable;

执行编辑命令

Internet Explorer 5.5 中的大多数基本编辑功能可通过发出命令来访问。MSDN Online 上的文档列出了可用的命令,并说明了要使用哪些参数。

要执行编辑命令,可调用 document.execCommand,并传递对应于命令 ID 的字符串。另外还有可选的第二个参数,该参数指定如果可以应用的话是否显示此命令的用户界面。传递整数 1 将显示用户界面,整数 0 将跳过它。这个参数通常不用于编辑命令。因为默认值为 0,所以假如您没有使用第三个参数(在这种情况下,还必须为第二个参数传递值),一般可以不管它。第三个参数也是可选的,在可应用的情况下,使用它来将任何所需参数传递给该命令。

例如,要打开多项选择功能,应当调用 document.execCommand("MultipleSelection") 要打开现场调整大小功能,只需调用 document.execCommand("LiveResize")。要打开 2D 定位,请调用 document.execCommand("2D-Position")

注意 2D 定位只能对 CSS 样式已设置为 position:absolute 的元素有效。

下例(见图 1)使用了 contentEditable 属性、unselectable 属性和三个可执行的命令来创建一个可在 Web 页上使用的简单的小文本编辑器。很重要的一点是,div 语句在另一个 div 语句中,而外层 div 底部有三个按钮。按钮使用 document.execCommand 方法来格式化当前选定内容的样式。内部 div 具有 contentEditable 属性,而外部 div 和按钮是不可选定的。由于它们是不可选定的,所以用户可以单击它们而不会破坏当前的选定内容。这对按钮尤其有用,因为用户可以选定 contentEditable 区域中的一些文本,然后单击粗体按钮、斜体按钮和下划线按钮,而不必重新选定文本:

<div align=center>
<div unselectable="on" align=center 
 style="height:300; width:400; background-color:powderblue; border:outset powderblue">  
  <br>  
  <div id=foo contenteditable align=left    
   style="height:250; width:350;background-color:white; font-face:Arial; padding:3;    
   border:inset powderblue; scrollbar-base-color:powderblue; overflow=auto;">  
  </div>  
  <br>  
  <button unselectable="On" onclick='document.execCommand("Bold");foo.focus();'   
   style="width:80; background-color:powderblue; border-color:powderblue">   
   <B>粗体</B></button>  
  <button unselectable="On" onclick='document.execCommand("Italic");foo.focus();'    
   style="width:80; background-color:powderblue; border-color:powderblue">   
   <B><I>斜体</I></B></button>  
  <button unselectable="On" onclick='document.execCommand("Underline");foo.focus();'    
   style="width:80; background-color:powderblue; border-color:powderblue;">   
   <B><U>下划线</U></B></button>
</div>
</div>

图 1 中值得申明的另一点是,现在可以指定滚动条的颜色了!(这是 Internet Explorer 5.5 的另一个新功能)。

图 1. 创建文本编辑器

保持可编辑的内容

如何保持可编辑的内容由您决定。如果您正在使用 Active Server Pages (ASP),您可以在窗体中包括可编辑的元素,之后使用 Post 方法将它们张贴到 ASP 页,然后以任何方式将它们存储在服务器上。有关 ASP 页的内容包含在 ASP SDK 中,这里不作详细说明。另一个方法,也可能是更有趣的方法,是使用 UserData 行为将数据保持在客户端。

UserData 行为

UserData 行为是将 contentEditable 元素中的内容保持在用户计算机的某个存储区中的最好方法。行为是 Internet Explorer 5.0 中引入的一种封装可重用脚本和/或 HTML 的方法。行为存在于它自己的、称为 HTC(HTML 组件)文件中,该文件被位于客户端文档的文件头中的 CSS 样式段加以引用。将行为应用到元素所用的方法与应用 CSS 样式相同。一旦行为与某个元素相关联,则属于该行为的所有方法都将被调用到该元素上。

UserData 是行为具有强大功能的极好范例。通过为在 SaveLoad 方法中所指定的 UserData 存储指定不同的名称,可以使用 UserData 行为来将多个元素的内容保持在单个页面上。唯一的限制是每页不能存储超过 64KB,每个域的限制则为 640KB。下一个范例展示如何保持单个 contentEditable 元素中的内容。

该范例中的元素是一个名为“foo”的 contentEditable div 语句。注意,在文件头的样式说明中,说明了 UserData 行为。通过说明元素的类为“userData”,行为被附加到 contentEditable 元素上。这样,可以访问由 UserData 行为显露的方法,如 setAttributegetAttributeLoadSave,就好象它们是元素自身的方法一样。(只要属性名在 getAttributesetAttribute 方法中是一致的,而存储名在 LoadSave 方法中是一致的,就可以以任何名称命名用来保持数据的存储和属性。)

<html>
<head>
<style> .userData {behavior:url(#default#userdata);} </style>
<script for=window event=onload>
 DoLoad();
</script>
<script for=window event=onbeforeunload>
  DoSave();
</script>
<script>
function DoSave(){
  foo.setAttribute("content", foo.innerHTML);
  foo.save("EditContent");
}
function DoLoad(){
  foo.load("EditContent");
  content = foo.getAttribute("content");
  if (content != null) foo.innerHTML=content; 
}
function DoClear(){
  foo.innerHTML = "";
}
</script>
</head>
<body>
<p align=center>
  <button onClick='DoSave()'>保存</button>
  <button onClick='DoClear()'>清除</button>
  <button onClick='DoLoad()'>加载</button>
</p>
<div id=foo class=userData contentEditable=true style="width:100%;height:90%">
</div>
</body>
</html>

图 2 展示了一个 contentEditable div 语句和三个按钮,它们允许用户保存 div 的内容、加载所保存的内容和清除当前的内容。另一个好的技巧是,当用户转到其它页时,window.onBeforeUnload 事件处理程序将自动存储用户输入的内容。然后,当他们返回时,window.onLoad 事件处理程序将自动还原它。当用户返回您的 Web 页并发现他们上次留下的相同内容仍然存在,他们一定非常吃惊。

图 2. 使用 UserData 行为保持数据

元素行为和编辑

元素行为是一个完全自我约束的自定义元素,可以将它当作固有的 HTML 控件。在前面有关保持的内容中,我们看到了 UserData 行为,该行为可以与任何元素关联。与标准行为相比,元素行为有其自己的元素标记,并且它不能应用到其它任何元素。行为不能脱离元素本身。

“viewlinked”元素行为:无需将生成该 UI 的 HTML 插入到调用它的文档中,其用户界面即可在浏览时显示。当用户查看 Web 的源文件时,他们只能看到代表该元素的标记,用户永远无法看见导致元素外观和动作的源文件。只有元素行为可以是 viewlinked。

有关元素行为的另一个重要情况是,无论元素标记什么时候可见于分析程序,行为都是可用的。永远不会出现元素在那里,而行为还没有加载的二者分离的情形。所有这些优点,使得元素行为成为创建可随时随地重复使用的、您自己的 HTML 控件的最好方法。

一个简单的例子

在该范例中,将获得简单的小文本编辑器(图 1),另外添加几个按钮使它更有趣,将它封装在一个 HTC 文件中,并添加几条线以告诉分析程序将它当作 viewlinked 元素行为。之后,我们将看见如何在 HTML 文件中创建该组件的实例。

HTC 文件

下面的代码是一个 HTC 文件,该文件包含了定义组件的源。注意,在顶部的 public:component 说明中包括了标记名称(在这里是“editBox”)。当新组件被插入 HTML 文件中时,这就是用来标识该新组件的名称。在 public:component 说明中的其它说明是 public:defaults viewLinkContent 说明, 它指定该元素行为是 viewlinked 的。将这些说明添加到文件顶部,并用 .htc 扩展名保存该文件,这样就完成了把新创建的 DHTML 转换成元素行为的全部操作。在这里,我们将该文件命名为“editBox.htc”。(并不是一定要将文件命名为与元素本身相同的名称,这样做只是为了便于记忆。)

<public:component tagName=editBox>
<public:defaults viewLinkContent/> 
</public:component>
 
<div unselectable="on" align=center style="height:250; width:425;

background-color:powderblue; border:outset powderblue"> <br> <div id=foo contenteditable align=left style="height:200; width:370;background-color:white; font-face:Arial; padding:3; border:inset powderblue; scrollbar-base-color:powderblue; overflow=auto;"> </div> <br> <button unselectable="On" onclick='document.execCommand("Bold");foo.focus();' style="background-color:powderblue; border-color:powderblue" title="粗体"> <B>B</B></button> <button unselectable="On" onclick='document.execCommand("Italic");foo.focus();' style="background-color:powderblue; border-color:powderblue" title="斜体"> <B><I>I</I></B></button> <button unselectable="On" onclick='document.execCommand("Underline");foo.focus();' style="background-color:powderblue; border-color:powderblue;" title="下划线"> <B><U>U</U></B></button> <button unselectable="On" onclick='document.execCommand("StrikeThrough");foo.focus();' style="background-color:powderblue; border-color:powderblue; text-decoration=line-through" title="删除线"> <B>S</B></button> &nbsp;&nbsp; <button unselectable="On" onclick='document.execCommand("SuperScript");foo.focus();' style="background-color:powderblue; border-color:powderblue" title="上标"> <B>^</B></button> <button unselectable="On" onclick='document.execCommand("SubScript");foo.focus();' style="background-color:powderblue; border-color:powderblue" title="下标"> <B>_</B></button> &nbsp;&nbsp; <button unselectable="On" onclick='document.execCommand("InsertOrderedList");foo.focus();' style="background-color:powderblue; border-color:powderblue" title="已排序列表"> <B>OL</B></button> <button unselectable="On" onclick='document.execCommand("InsertUnorderedList");foo.focus();' style="background-color:powderblue; border-color:powderblue" title="未排序列表"> <B>UL</B></button> <button unselectable="On" onclick='document.execCommand("Outdent");foo.focus();' style="background-color:powderblue; border-color:powderblue" title="突出"> <B>&lt;&lt;</B></button> <button unselectable="On" onclick='document.execCommand("Indent");foo.focus();' style="background-color:powderblue; border-color:powderblue" title="缩进"> <B>&gt;&gt;</B></button> &nbsp;&nbsp; <button unselectable="On" onclick='document.execCommand("JustifyLeft");foo.focus();' style="background-color:powderblue; border-color:powderblue" title="左对齐"> <B>|&lt;</B></button> <button unselectable="On" onclick='document.execCommand("JustifyRight");foo.focus();' style="background-color:powderblue; border-color:powderblue" title="右对齐"> <B>&gt;|</B></button> <button unselectable="On" onclick='document.execCommand("JustifyCenter");foo.focus();' style="background-color:powderblue; border-color:powderblue" title="居中"> <B>&gt;|&lt;</B></button> &nbsp;&nbsp; <br> <button unselectable="On" onclick='document.execCommand("Cut");foo.focus();' style="background-color:powderblue; border-color:powderblue"><B>剪切</B></button> <button unselectable="On" onclick='document.execCommand("Copy");foo.focus();' style="background-color:powderblue; border-color:powderblue"><B>复制</B></button> <button unselectable="On" onclick='document.execCommand("Paste")' style="background-color:powderblue; border-color:powderblue"><B>粘贴</B></button> &nbsp;&nbsp; <button unselectable="On" onclick='document.execCommand("Overwrite");foo.focus();' style="background-color:powderblue; border-color:powderblue"><B>覆盖</B></button> </div>

HTML 文件

现在既然已经看过了 HTC 文件,接着让我们来看看 HTML 文件。在该文件中与任何其它 HTML 文件唯一不同的内容是位于文件顶部的 html 说明中的 namespace 属性,另一个不同是处理指导 (PI),它告诉分析程序在哪里找到 editBox 元素的执行文件。当碰巧名称相同的单独 HTC 文件中有两个不同的元素行为时,就必需要有 namespace 属性。namespace 提供了分辨它们的方法。导入语句简单地告诉分析程序当它看见标记名有前缀“x”时,它应当在指定的执行文件中查找该标记的定义。所以,无论什么时候使用用于新组件的标记,都必须用在 PI 中已经说明的 namespace 来给该标记加上前缀。(与在 XML 中的 namespaces 不同,这个 namespace 不是“统一资源名 (URN)”,并且它与标记本身没有固有关联。namespace 由 HTML 文件的创作者定义,并且对说明它的文件来说,它位于本地。它类似于在特殊 XML 文件中与 XML namespace 相关联的前缀。)

<html xmlns:x>

<head>

< import namespace=x implementation="editBox.htc" />

</head>

<body>

<x:editbox>

</body>

</html>

图 3. Viewlinking 元素行为

摘要

在了解如何创建简单的文本编辑器作为元素行为后,您就可以轻松地对它进行扩展了,方法是添加持久性、使用前面介绍的 UserData 行为、添加用于选择字体和字体大小的控件。还可以对它进一步扩展,比如将菜单或下拉框添加到 UI 以便插入控件、图象和字幕,以及支持 2D 绝对定位、多项选定和现场调整大小。(无疑,还可以制作出更好看的用户界面!)通过合并使用浏览时编辑功能、UserData 持久性和元素行为,要想创建很棒的编辑组件几乎不受任何限制!

当然,并不是说您必须执行元素行为才能创建可编辑的 Web 页。Viewlinking 只是提供绝佳的方法来压缩及重复使用您所建立的行为(这样可以避免泄露您的 HTML 源文件)。

在了解 Internet Explorer 5.5 中所有最棒的新编辑功能之后,剩下的事就看您的了。相信您将会成为您公司中第一个提供实时、“所见即所得”可编辑 Web 页的人!(您的同事一定非常羡慕又嫉妒。)

发表评论:

    昵称:
    密码:
    主页:
    标题:
Powered by Oblog.