西游记大鹏鸟扮演者:浏览器 HTML 编辑: (1) | Opera 中国

来源:百度文库 编辑:九乡新闻网 时间:2024/04/30 01:23:46

简述

Tim Berners-Lee 1990年创建的第一个浏览器支持所见即所得( WYSIWYG )方式编辑网页。Web 被设计为可读可写的媒介。然而后来的浏览器只能读取网页,只能通过表单控件输入简单的纯文本信息。

Internet Explorer 5 又重新开始支持 WYSIWYG 编辑:designMode 属性允许用户修改整个页面。然而此属性没有得到普遍使用,也许是因为它被淹没在一堆 Windows-专用的 IE 扩展中。

最近几年微软的竞争者—— Mozilla, Safari 和 Opera ——也实现了类似的编辑功能。WHATWG-工作组正致力于标准化网页编辑系统—— HTML 5 中引入了 designMode 和 contentEditable DOM 属性。网页的 WYSIWYG 编辑功能将是未来 Web 的重要组成部分。

本文介绍在浏览器中使用 HTML 5 编辑功能的基本方法,及可能碰到的问题。包括以下内容:

  • 不同的开启编辑功能的方法
  • 编辑命令
  • 编辑产生的 HTML 代码
  • 与 DOM 交互

本文是两篇系列文章的第一篇,第二篇将详细介绍如何实现 HTML 编辑器。

注意: 我只介绍最新版本的浏览器(Opera 9.5, Firefox 2+ 和 Safari 3)支持的编辑功能,之前版本的浏览器充满了 bug 。IE 浏览器的编辑功能从 IE 5.5 开始就没有重大改进。)

编辑系统概览

编辑系统允许编辑整个网页或部分网页。其包含以下几个特点:

  • 插入光标( caret )显示目前插入点。用户可通过键盘或鼠标移动光标、选择文本、输入或者删除内容。
  • 有些浏览器提供用户界面以改变元素大小或位置;这些可编辑元素包括图像、表格和表单控件。
  • 浏览器内建了一些标准编辑命令—— Bold, Italic, InsertLink, Paste, Undo 等。可以通过快捷键或者通过 command API 利用脚本使用这些命令。使用 command API 可以轻松的实现 HTML 编辑工具栏。
  • 通过 Range 和 Selection API 可以任意修改 HTML 文件;可以用此方法实现自定义编辑命令。
  • 编辑系统允许用户修改 HTML 。系统不管你如何使用修改后的 HTML 文档。比如你想把修改后的网页复制到服务器中,可通过脚本实现。

在使用编辑系统时需要注意:

  • 编辑命令的定义不是很清晰,不同的浏览器生成的 HTML 有较大差异。
  • IE 编辑功能自从2000年的 IE 5.5 以后就未有重大变化。其产生的 HTML 代码可能令人吃惊——你很可能在其中发现 标签!

启用编辑功能

有两种方法可在网页中创建可编辑部分 —— designModecontentEditable 属性。

通过设置 document 对象的 designMode 属性为 true ,窗口或框架就变为可编辑的。(注意:在 IE 中此操作会使文档引用失效;应从 window 对象中重新获取)。通常会产生一个编辑窗口( designMode 模式的 IFrame )。

所有包含文字的元素都可以通过设置 contentEditable 为 true 变为可编辑的。( Firefox 2不支持 contentEditable,但是 Firefox 3 和 IE, Opera 和 Safari 支持)。

键盘编辑

和其他编辑器类似,浏览器 HTML 编辑也可以使用鼠标和键盘。当文档获取 focus 后会显示插入光标,可通过鼠标或键盘移动插入光标。可通过键盘输入或删除字符。可通过键盘或鼠标移动、删除或替换选中文本。

一个很好的特性是所有的键盘编辑动作都被记录而且可以撤销。(如何使用 Undo 命令参看下文)

按下 Enter/Return 键后的处理方法比较复杂。很难定义此动作应该产生怎样的 HTML 代码,不同的上下文将产生不同的结果;不同的浏览器产生的 HTML 代码也存在很大差异。如果插入光标位于 (非空的) p 元素中,所有浏览器都应该闭合此 p 元素,插入新的(使用相同属性) 并把插入光标置于新的 p 元素。( Mozilla 会在插入光标后插入 (多余的) br 元素。)
例子如下 (在下面的例子中|符号代表插入光标位置):

bla bla|

在 IE 或 Safari 中按下回车后:

bla bla

|

如果插入光标在 (非空) h1 元素之后,所有浏览器都会关闭 h1,但 IE 和 Opera 会插入新的 p 元素并将光标置于 p 元素中;Safari 会插入新的 h1 元素并将光标置于新元素中; Mozilla 不创建任何元素,但会在光标后插入两个 br 元素。如:

bla bla|

在 IE 或 Opera 中按下回车后:

bla bla

|

但在 Mozilla 中变为:

bla bla

|

在 Safari 中变为:

bla bla

|

如果你直接在 body 元素中输入 (而不使用其他容器元素)并点击确定,在 Mozilla 中会插入 br 元素。IE 和 Opera 会把前面的文字转换成 p 元素并插入新的 p元素;而 Safari 将插入 div 元素。

如果在 div 元素中输入“回车”, Safari, Opera 和 IE 会关闭当前的 div 并插入新的 div。Mozilla 会在当前 div 中插入一个 br 元素。

如果光标在嵌套的块级元素中( block level element),所有浏览器都会关闭最内层的元素并把光标置于次外层块元素中。

结论:这真复杂!令人惊奇的是 IE 居然是最好的实现,其总能保证块级元素的正确性。Mozilla 最烂,总用br代替块元素,这样就无法为文字设置样式了。

光标位置

插入光标可在字符间移动。但是无法看到光标相对于标签的位置。所有浏览器的处理方法一致。光标相对于块级元素的处理方法:光标总是位于最内层的块元素。不能把光标置于两段之间。

如下所示,| 符号显示可能的插入点位置:

|P|1|

|P|2|

|P|3|

|P|4|

光标相对于 inline 元素处理方法:如果光标在文字左边则被认为在所有元素外;如果光标在文字右边则被认为在元素内:

|A|B|C|

所以如果你在加粗文字 range 左边输入文字,新文字不是加粗的。如果你在 range 右边添加字符,则新文字也是加粗的。

删除

如果删除段落边界,结果是一致的 —— 左边的块 “获胜” 右边的内容会被加入到左边元素中:

Overskrift

|Text

按删除后结果如下:

Overskrift|Text

Safari 浏览器的实现方法比较聪明 (或者比较糟糕,这取决于你的喜好):

Overskrift|Text

编辑 Object

浏览器提供用户界面以编辑特殊的 HTML 对象。

IE 允许改变图像、表格、表单元素大小,或通过拖拽改变元素位置 (当选中元素后,出现拖拽图标)。

Mozilla 允许改变图像和表格大小,并允许通过附加控件创建新的行和列。Mozilla 也支持改变元素位置,此功能的 UI 是专利保护的并只能用于 Mozilla 浏览器,且无法定制使用。

编辑命令 (Editing command)

不同浏览器支持不同编辑命令。这些命令产生的 HTML 代码没有被标准化,因此不同浏览器产生结果不同。如,在 IE 中“加粗” 命令生成代码为:

Hello!

而 Safari 生成代码为:

hello!

产生的代码都是比较老式的代码风格,至少在 IE 浏览器中如此。很多编辑命令会产生已遭弃用的 font 标签 (如 23);产生的 HTML 无法通过 XHTML 验证,有时甚至不是合法的 HTML!

Opera 的 HTML 编辑命令类似于 IE,也使用 元素。Safari 通过 和内联 CSS修改文本样式。Safari 方法的优点是生成的 HTML 代码可以通过 HTML 4.01 Strict 验证。

Mozilla 支持上面两种方法——既可以和 IE/Opera 产生显示性元素,也可以如 Safari 一样产生样式属性。

如果你重视 HTML 验证,你应该在服务器端实现检查功能,以把修改后网页变为合法 (X)HTML文件(无论如何你都应该这样做,以防止 XSS-攻击)。

键盘快捷键

许多编辑命令可以通过快捷键实现:如 Ctrl/Cmd + B 设置加粗,Ctrl/Cmd + Z 是撤销命令等。但不同浏览器中有不同的快捷键。

不能重新设置快捷键,但可以通过脚本截获键盘事件,以重新定义快捷键功能。

command API

比如你想实现一个文本编辑工具栏,用户可以使用此工具栏改变文字格式。这可以通过命令 API 实现。此 API 和常见的 DOM API 不同,其实际上是允许脚本的 IOleCommandTarget 接口——此接口是微软用于同步工具栏的 COM 接口。

command API 在 Document 对象中,由 execCommand 方法和一系列以 “query” 开头的方法组成(这些方法返回 command 相关信息)。

所有的方法的第一个参数是 command ID ,即是字符串形式的 command 名称。command API 的方法如下所示。

ExecCommand

对选中元素执行 command 。有些命令设置/取消属性——如 bold 命令如果作用于已经加粗的文本,则会取消加粗。有些命令要求参数值——如 forecolor 命令需要颜色值。有些命令使用标准对话框——如 link 命令会显示对话框以允许用户输入 URL。无法自定义对话框,但是可以不用:

result = document.execCommand(command, useDialog, value)

上例详细解释:

  • command: 字符串;命令名称。
  • useDialog: 布尔值;是否显示 built-in 对话框 (并不是所有命令都需要对话框)。
  • value: 命令参数值。并不是所有命令都需要参数值;如果使用了 built-in 对话框,则此值将来自对话框。
  • result:如果命令被执行了则返回 true ;否则返回 false(如用户在对话框中选择了取消,或者命令无法执行)。

如果未选中任何内容 (只有插入光标),不同浏览器对于文本格式命令的解释不同。 如果插入光标位于单词中,IE 会将格式命令作用于整个词;而其他浏览器只作用于下一个字符。

QueryCommands

查询命令主要用于获取关于选中内容的信息。

QueryCommandEnabled

查询此命令是否能用于当前选中内容。如只有选中元素位于链接中才能使用 “删除链接” 命令。如果所选内容并非位于可编辑区域中,所有的命令都将被禁用。

QueryCommandState

查询此命令是否已经作用过选中内容。如当前选中内容为粗体,则 bold 命令的返回值为 true 。

QueryCommandValue

此函数返回值即为 execCommand 命令中使用的值,如 ForeColor 返回当前选中内容的颜色值 (字符串形式) 。

不同浏览器的返回值格式不同。如 ForeColor 在IE中返回十六进制颜色码 (如 #ff0000),而在其他浏览器中返回 RGB 形式的颜色值,如 Rgb(255,0,0)

有些返回值甚至根据浏览器 locale不同而不同,如 FormatBlock 在 IE 中返回浏览器所用语言表示的段落名称。

bold 这样的命令没有返回值,只返回 false。(API 另外包含两个方法,queryCommandSupportedqueryCommandIndeterminate,但这两个函数实现普遍质量不高,不堪重用。)

Range 和 Selection API

built-in 命令对处理一些简单问题比较有用,但无法随心所欲编辑网页。通过 Range 和 Selection API 可以任意的修改 HTML ,也可以实现自定义命令。

所有通过 DOM 的网页修改都会破坏撤销栈( undo-stack ),撤销栈用于实现撤销/重做命令。这虽然很不方便,但却是为了实现自定义命令必须付出的代价。

range/selection API 有两个核心类:

  • Range ——网页中的字符之集。Range 可以跨多个元素。Range 有起点和终点。如果起点和终点相同,则称 range 为收缩的(collapsed)。
  • Selection ——代表当前选中内容。selection 包含一个高亮显示的 range 。如果选中的 range 是收缩的,则显示为一个插入光标(caret)。

(Range 和 selection 只能用于可编辑区域内。可在只读文档中创建 selection 。但是只读文档中的selection 不能是收缩的,因为只读文档无法显示 caret。)

这些概念在所有浏览器中都是一样的,但是具体的 API 却不完全相同——与其他浏览器不同,IE 使用自己定义的 range 和 selection API,而其他浏览器使用的是W3C DOM Range API 和未标准化的 selection API。

最大的不同时 IE 中 range 内容是字符串型式的 HTML 标记代码。而在 W3C DOM Range API 中 Range 内容通过 DOM 树访问。

Range 示例

下面是两种不同的实现方法:

在 IE ( editWindow 即是 designMode 模式下的框架)中:

var rng = editWindow.document.selection.createRange();rng.pasteHTML("" + rng.htmlText + "");

在 Mozilla中

var rng = editWindow.getSelection().getRangeAt(0);rng.surroundContents(document.createElement("code"));

Control 选择

IE 支持控件选择,但和 range 选择不同。点击如图形、表单控件或表格边框等对象时将被视为控件选择。

可以通过 Ctrl 键在 IE 中选择多个控件。其他浏览器中不存在控件选择概念;在这些浏览器中所有选择都是 text range 。