首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

构建一个简单的 WYSIWYG Web 页面编辑器(1)

构建一个简单的 WYSIWYG Web 页面编辑器(1)

本文描述一个简单的系统,该系统让 Web 站点用户可以构建自己的 Web 页面。通过这个系统,用户可以在它们的页面上放置和安排文本和图像,然后保存他们的工作。本文中的代码是独立的,没有使用第三方的库。虽然在现实中您未必这么做,但这为研究实现技巧提供了很好的基础。
体系结构这个系统中的代码可分为 5 个部分:
  • 小部件:小部件 是组成 Web 页面的一个个的元件。本文只考虑两种小部件:一种是可编辑的文本小部件,另一种是图像小部件。当然,您也可以创建很多其他类型的小部件。但是,这里我更感兴趣的是支持小部件的基础设施,而不是多种多样的选项。
  • 布局:这个系统的整个功能就是让您可以通过创建、移动和缩放文本和图像小部件来创建 Web 页面。这里并没有发生什么大事情 — 只是一些鼠标事件处理器、<div> 大小调整等。很多文章和教程已对此作了大量的描述,本文不再重复。
  • 持久性:用户必须保存他们的工作,并在以后再次装载它,所以需要一个持久性机制。您将使用基本的串行化将数据转换成可保存的格式,并使用文档对象模型(Document Object Model,DOM)存储来存储它。DOM Storage 是在 HTML version 5 规范中定义的,较新版本的 Mozilla Firefox 中实现了该功能。
  • 点击-拖动功能:网上有很多关于用 JavaScript 代码实现点击-拖动功能的文章和教程,所以在此不再赘述。相反,我关注实现它的基本结构,因为我认为它是模块化的。
  • 拖放功能:和点击-拖动功能一样,可以完全用 JavaScript 代码实现拖放功能。但是,现代浏览器和操作系统越来越多地支持本地拖放功能,这样做有利也有弊。本文会讨论这些问题。
小部件根据 Wikipedia 上的定义,小部件是 “一个对象的占位符名称,具体而言,它是一个机械设备或已制成的设备的占位符名称”。在软件领域,小部件常常指自含的 GUI 元素,可以随意将它们放在一个页面上,或者将它们组合成一个整体。
这个系统包含两种小部件:一种用于文本,另一种用于图像。文本小部件是可编辑的,图像小部件则不能编辑。这是非常基本的一组小部件,与商业系统中多种多样的小部件区别很大,但能够满足演示的目的。本文感兴趣的是围绕小部件发生的事情。
小部件属于对象JavaScript 是一种面向对象语言,所以小部件就是对象。但是,JavaScript 语言是非常灵活的。它更倾向于基于原型,而不是基于类,它没有单独的、内建的继承技术。这两个小部件首先是 GUI 元素。实际上,Image 对象是一个 HTMLImageElement。它的构造函数如清单 1 所示。
清单 1. Image 的构造函数
1
2
3
4
5
6
function Image( url ) {
  var self = elem( "img" );
  self.src = url;
  // ...
  return self;
}




这种风格的构造函数并不常见,它返回一个称作 self 的值。在 JavaScript 语言中,构造函数实例化由运行时系统提供的底层的 Object,这个 Object 返回给构造函数的调用者。
但是,这个构造函数返回一个值,这意味着这个值取代常规的 Object,而后者将被抛弃。定制对象覆盖了默认的 Object。
注意:我将这个值称作 self,因为我不能重新赋值传统的 this。这导致的结果是,Image 对象实际上是通过调用 elem() 创建的一个 HTMLImageElement。这意味着 Image 是 HTMLImageElement 的一个子类,可以将它直接放到 DOM 树中。
可编辑的小部件这个系统中的另一种小部件是文本小部件,它被称作 EditText,因为文本是可编辑的。EditText 构造函数也覆盖构造函数返回值,如清单 2 所示。
清单 2. EditText 的构造函数
1
2
3
4
5
6
7
function EditText( text )
{
  var self = Box();
  self.shower = elem( "div" );
  // ...
  return self;
}




self 对象是由 Box 构造函数创建的,后者也覆盖返回值,如清单 3 所示。
清单 3. Box 的构造函数
1
2
3
4
5
6
7
function Box()
{
  var self = elem( "div" );
  sty( self, "border", "none" );
  // ...
  return self;
}




因此,EditText 对象实际上是一个 Box 对象,后者实际上又是一个 HTML DivElement。因此也可以将它直接放入到 DOM 树中。
Box 对象是一个 <div>,其中包含另一个 GUI 元素。它有一对 getting 和 setting 方法,用于访问和设置这个包含的元素。EditText 元素需要这些元素,因为 EditText 有两种模式。当编辑文本时,它是一个文本区,当显示时,它是一个常规的 <div>。当 EditText 对象从一种状态切换到另一种状态时,它调用 Box.set() 方法来更改外观。
返回列表