本文内容来自于本人翻译的《Dojo构建Ajax应用程序》一书,该书由机械工业出版社出版。
以下为该书封面(点击图片可以进入到china-pub上该书的页面):
以下为该书的目录:
202第一部分Dojo指南.1a1c1ac111c111a1a1 |
203理解Dojo:指南2a2c2ac222c222a2a2 |
204使用Dojo进行客户端验证3a3c3ac333c333a3a3 |
205使用Dojo与服务器端协同工作4a4c4ac444c444a4a4 |
206使用DojocWidgets5a5c5ac555c555a5a5 |
207使用Dojo处理表单6a6c6ac666c666a6a6 |
208第二部分cDojocWidgets7a7c7ac777c777a7a7 |
209DojocWidgets简介8a8c8ac888c888a8a8 |
201DojocFormcWidgets9a9c9ac999c999a9a9 |
201DojocLayoutcWidgetsc..10a10c10ac101010c101010a10a10 |
201其他专门的DojocWidgets11a11c11ac111111c111111a11a11 |
201第三部分cDojo详解12a12c12ac121212c121212a12a12 |
201Dojo是什么?13a13c13ac131313c131313a13a13 |
201Dojo的技术描述14a14c14ac141414c141414a14a14 |
201对象与类15a15c15ac151515c151515a15a15 |
201String与JSON16a16c16ac161616c161616a16a16 |
201事件与事件处理17a17c17ac171717c171717a17a17 |
201AjaxcRemoting18a18c18ac181818c181818a18a18 |
202处理DOM19a19c19ac191919c191919a19a19 |
201测试与调试...20a20c20ac202020c202020a20a20 |
第1章 理解Dojo: 指南
耳听为虚,眼见为实。
—中国谚语
灵感来源于本章开头所引用的谚语,我相信讲解新技术最好的方式之一就是给出一个简单的示例。因此我将以一个指南作为本书的开始,该指南将使用Dojo Toolkit来增强一个基本的HTML表单。从本章开始一直到第五章——使用Dojo处理表单都将介绍该指南,同时这五章也构成了本书的第一部分——Dojo指南。
指南简介
假如你是一个Web开发者(如果你正在阅读这本书,那么对此就没什么好奇怪的了),有人建议你向站点中增加一些Ajax特性。也许提出该需求的人正是你的老板,甚至是老板的老板,但他可能连Ajax是什么都不知道,更不用说哪些特性有用了。也许你有点不太自信。想象一下,你之前的经验几乎都在服务器端,使用Java或者其他服务器端技术,你对HTML和JavaScript的经验非常有限。这就是接下来几章中你开始了解Dojo Toolkit时所处的场景。
为了进一步说明该场景,假设你已经听说过JavaScript编程语言非常强大,有很多JavaScript库和框架可以协助你充分利用其强大的功能。你已经决定使用Dojo Toolkit,因为你经常访问的一些Web站点和论坛推荐它。同时你也准备将应用中访问最频繁的一个页面“Ajax化”。
该指南将通过几个步骤向你介绍如何使用Ajax特性来更新页面。我们将采用小步前进的方式来增强该页面,每一小步都会重点说明一个具体的问题。通过这种方式,我们将会看到Ajax允许我们往Web页面中增加的各种特性,同时我们也会看到如何使用Dojo Toolkit来实现这些特性。
1.1.1 本指南的目标
本指南的首要目标就是向你展示如何使用Dojo Toolkit将一些常见的Ajax特性增加到web页面中。该指南从简单处着手。换句话说,它专注于容易实现且对可用性提升大有裨益的一些特性。它不会对Dojo特性进行面面俱到的讲解,也不会涵盖我们实现的所有特性。你可以将它当作增强Web站点的第一步。
该指南的另一个主要目标就是以最简单的方式实现一些特性。尽管Dojo的大多数特性既可以声明方式(通过HTML标记)也可以编程方式(通过JavaScript)实现,但我们首先以声明方式实现,因为大多数的服务器端Web开发者更熟悉HTML标记,相比之下,对JavaScript就差一些了。当然了,我们也会使用一些JavaScript来作为各种东西的粘合剂。
1.1.2 使用Dojo的目的
我们使用Dojo想要得到什么呢?首要的是——想让页面的可用性更好。我们在很多地方都会这样想。页面的执行应该更快点。看起来更漂亮点。操作起来更简单点。可以帮助用户准确获得其想要的信息,这就要求页面的导航更简单。但同时在用户访问Web页面时,我们不应改变其操作习惯。我们在不断增强可用性的同时不能以牺牲用户已有的体验为代价。
我们该如何改进可用性呢?Dojo对已有的HTML表单元素进行了增强,提供了额外的功能。这些增强会使当前的表单元素可用性更好。
我们可以通过如下两种方式来改进性能:让系统运行的更快或者是让系统看起来运行的更快。让一个过程看起来运行的更快的理想方式就是在其运行的同时用户可以做一些其他事情而不是在那干等着。Ajax使用了非常棒的机制来支持该技术。我们将使用Dojo让页面向服务器端发送异步请求,同时用户的操作可以继续而不被打断。对用户来说,该页面看起来运行的更快、响应也更快了。
我们可以在用户输入数据时就进行验证,以此来改进数据验证过程。Dojo可以将小部分验证请求发送到服务器端而无需提交整个表单。如果合适的话,我们甚至想采用桌面应用那种数据验证方式——根据用户的按键进行验证。
我们还希望这些特性容易实现。我们想利用对于HTML的开发经验,在使用JavaScript时,让编程模型保持一致而强大。我们希望相比于完全由我们自己来开发功能,所需编写的代码量更少。代码少意味着出错的机会小。当你学习Dojo时,你会发现你所掌握的内容对你进一步探索Dojo会大有裨益。当事情变得复杂时,你可以使用工具以辅助调试。简言之,Dojo提供了非常棒的编程环境,绝对值得你期待。
最后,你可以看到我们会一直惊讶于Dojo带给我们的好处,而这些好处不需要任何额外的工作就可以得到。例如,我们会看到增加的任何特性都可以在各种浏览器中以一致的方式呈现出来。同时我们还会看到用来支持Web的易用性(Accessibility)及国际化(Internationalization)标准的一些可视化元素。
我们已经给Dojo带上了高帽。我们要求不少,但却不想费太多劲。Dojo真的行吗?这需要我们去探索。我们首先以一个页面作为增强的基础,通过该页面确定好我们希望解决的各种问题。
1.2 一个标准的HTML数据输入表单
首先从我们的应用中选出一个页面作为Dojo增强的目标(图1.1)。该页面来自于一个假想的客户服务应用,该应用面向全国的电报公司,它允许客户创建帐号并请求服务。该指南对于我们“业务”操作的定义很含糊,因为你可能会猜到,该表单就是用来突出很多业务应用都会拥有的一些特定类型的功能。因此如果你能先将怀疑放在一边的话,那就让我们来检查一下该表单。
该页面的设计很一般——几乎一点设计都没有。它仅使用了一点样式,就这点样式也是很简单的。你的页面肯定比它强多了,但我们使用该简单设计以让示例保持足够的简单。
让我们将表单中的每个字段都过一遍,然后看看有没有可用性问题。接下来会谈到Dojo是如何解决这些问题的。
1.2.1 First与Last Name
第一个数据输入字段用来保存客户的first name。这足够直接,但我们已经有问题了。该字段的标签内容是:“First / Last Name:”,同时紧跟两个文本输入框。尽管用户可能明白该页面需要什么,但对于屏幕阅读器(有视觉障碍的人用其读取屏幕上的内容)来说还是困难些。
你可能会从可用性角度提出质疑:这让人感到不明就里。页面上的其他标签都仅指一个单独的文本框,而该标签却指两个。当将一个名字分为两部分时,last name就应该放在first name前吗?没有其他方式吗?问的好,但我们现在暂且不进行回答。记住,我们现在仅仅是找出问题。在后面的章节中将给出解决方案。
现在让我们看看这些字段的HTML标记。
<label for="firstName">First / Last Name: </label>
<input type="text" id="firstName" name="firstName" />
<input type="text" id="lastName" name="lastName" />
你以前可能没用过<label>标记,但它却可以让伤残人士更方便地访问你的站点。当标签不在输入字段前时,该标记将有助于屏幕阅读器,例如当标签位于不同的单元格中时。当使用级联样式表(CSS)时还可以轻松地将一个单独的样式增加到所有的标签上。另一个问题就是这两个字段中只有一个拥有<label>标记。
First name和last name字段都是必填的。但在这个标准的表单中并没有使用JavaScript,那我们如何做到这一点呢?并没有满足该要求的HTML标记或者是属性存在,因此我们准备将这个验证交给服务器端处理。这意味着用户只有在提交表单并收到来自服务器端的错误消息后才能知道哪些字段是必填的。
该如何显示错误消息呢?假如用户已经输入了一些表单数据,然后按下了“提交”按钮。接下来浏览器就会向服务器端发出一个请求,然后服务器就会对数据进行验证并将带有错误消息的表单返回给浏览器。我们希望服务器还会将用户已经输入的数据也返回来,这样用户就无需重新输入了。错误页面通常在页面上方显示所有错误消息。带有错误消息的页面看起来如图1.2所示。
1.2.2 用户名
我们的应用允许用户登录并管理自己的帐号,因此我们要求每个用户都要创建一个用户名。我们应该为用户提供一些指导以帮助其创建合适的名字,但这需要往页面中增加大量的文本,因此我们决定不这样做了。该表单就简简单单的要求一个用户名并提供一个文本输入框而已。
完成该功能的HTML标记非常类似于“First / Last Name:”字段,就一个<label>和<input type="text">标记,如下所示。
<label for="userName">User Name: </label>
<input type="text" id="userName" name="userName" size="20" />
我们通过设定size=”20”属性已经增加了一点儿客户端验证,以保证用户无法输入超过20个字符的名字。
该字段的一个问题也出现在验证上。用户可能想创建一个易记的简短用户名,但这也是其他用户的想法,这样该用户名就很有可能已经被使用了。那么我们该如何通知用户呢?请注意,直到用户提交页面时才能进行验证。服务器会检查用户名以确认是否已被使用了,如果被使用了,就会返回一个页面来重新显示表单并给出错误消息(同时还有其他字段的错误消息)。如果能给用户一些建议就更好了,这样他就不会再次输入已被使用了的用户名了。该建议应该基于用户想要注册的那个用户名。
1.2.3 Email地址
我们想通过Email与用户交流,因此需要一个Email地址。可以使用一个简单的文本输入框来存放用户输入的Email地址。
其HTML标记显示如下,它与页面上的其他文本字段也很类似。
<label for="email">Email: </label>
<input type="text" id="email" name="email" size="45" />
我们又一次通过设定字段的size属性来进行客户端验证。但有没有办法验证Email地址的有效性呢?我们可以使用两类验证。首先,Email地址的格式正确么?例如,是否包含“@”符号?是否以TLD如“.com”结尾?其次,它是一个真实的Email地址么?不幸的是,如果不实际创建并发送一个Email是没法验证后者的。尽管向用户发送一个密码并让他自己来验证用户名是一个好主意,但这已经超出了我们讨论的范围了。因此我们仅仅确认该Email地址的格式正确就行了。
1.2.4 地址
我们需要用户家庭地址的首行,同时使用一个文本框保存它。
其HTML与上面的字段都很类似。
<label for="address">Address: </label>
<input type="text" id="address" name="address"/>
该字段应该包含客户账单地址的首行,因此我们需要确保用户填写了该项。它是一个必填字段,但我们还是通过服务器端进行验证。
1.2.5 州
我们将用户所在的州作为其账单地址的一部分。因为州名有限,所以可以使用<SELECT>来提供州名的一个下拉列表,用户可以选择其中一个。下图显示了使用下拉列表的州名示例。
HTML提供了<SELECT>表单元素,它能提供一系列值的列表。下面展示了创建该字段所需的一些标记片段。
<select name="state" >
<option value="AL">Alabama</option>
<option value="AK">Alaska</option>
<option value="AS">American Samoa</option>
<option value="AZ">Arizona</option>
... additional state values not shown ...
</select>
由于州名有限,所以它们的值都可以列出来。对于这个字段,验证不是问题,问题在于行为。我住在伊利诺斯州(Illinois),经常网购,所以我常常要输入账单地址。当从表单中选择州名时,我首先会敲一个“i”,接下来“Idaho”就会跳出来,因为它是第一个以“i”开头的州名。这太棒了——尽管我不住在爱达荷州(Idaho)。接下来我敲一个“l”(小写的“L”),“Louisiana”又会跳出来。现在很多有成就的人都住在路易斯安那州(Louisiana),但我不是。问题在于<SELECT>标记将我的输入解释为两种不同的情况——每种都是一个单词的首字母,它没有将其当作一个单词的前两个字母。当我敲“il”时,我想看到所有以“il”开头的州名,只有Illinois符合这种情况。不幸的是,这不是<SELECT>标记的工作方式——当我敲“l”时,它显示的是“Louisiana”,这是因为它觉得我又一次敲了一个州名的首字母。
该问题并不是无法解决。有些浏览器就会按照我们期望的方式工作(将整个“il”当作州名的前两个字母),但我们想让页面在各种浏览器中都有一致的行为。
1.2.4 城市
这是需要的另一个字段。我们使用一个文本框存储用户的输入值。
其HTML与其他的文本字段一样。
<label for="city">City: </label>
<input id="city" name="city"/>
基本的HTML表单不会对该字段进行任何验证。但我们能否向用户提供一个城市的下拉列表呢,就像选择州名那样?每个州只有确定数量的城市,但其数量倒不少。整个美国大约有30,000多个城市。因此简单的在页面中列出这些值会增加页面的大小,使其加载速度变慢。另外列出所有城市也不太对头;我们需要列出用户所选择的州下的城市。这就需要我们使用一些JavaScript逻辑来进行处理,但在这个简单的表单中我们尽量避免使用JavaScript。
下拉列表的可用性也是一个问题。由于城市数量太多,导致很多城市都以相同的字母开头。敲入城市的首字母只会让用户看到一个长长的列表的开头。用户不得不向下拉动以寻找正确的值——这也太无聊了吧。
1.2.7 邮政编码
邮政编码是账单地址所需的最后一个字段。我们使用一个文本框来存储用户的输入。
其HTML与其他文本框的一样。
<label for="zipCode">Zip Code: </label>
<input type="text" id="zipCode" name="zipCode" size="10" /></br>
这需要验证。我们还是使用服务器端验证来保证该字段已被输入。服务器将返回一个包含表单、用户已输入的数据及所有验证错误消息的页面。该字段除了必填以外还需要执行什么验证呢?就像Email地址一样,它需要执行两类验证。数据格式是否正确?数据是否有效?
在美国邮政编码有两种形式。既可以是5位数字,又可以是5位数字,然后是一个破折号,接下来是4位数字。这意味着输入的数据既可以是5个字符长,也可以是10个字符长。HTML确实可以通过size属性来限制最大长度。然而它却无法限制最小长度。同时也没法限定需要使用一个破折号将邮编的两部分数字分开。这些检查服务器端都可以做,但只有在用户提交表单后才行。
还可以再进一步。就像州和城市一样,美国的邮编数量也是确定的。那我们能否使用<SELECT>将其列举出来呢?既然我们已经知道了州和城市的用法,可否将其应用于邮编呢?事实上这个逻辑比你想象的要复杂多了——一些城市有多个邮编,而一些邮编也可能被多个城市所用。当我们将地理范围扩大到美国以外,你会发现情况还要更复杂。尽管如此,为了保持该指南的简单性,我们还是讨论美国的情况吧,
关于该字段我们已经谈到了很多问题。记住,在指南的后面会给出解决方案的。
1.2.8 服务日期
我们的客户还想确定其电报服务的开始时间,因此我们提供了一个文本框用来存放其输入的开始服务日期。
其HTML与其他字段的一样。
<label for="serviceDate">Service Date:</label>
<input type="text" id="serviceDate" name="serviceDate" size="10"/>
对于该服务日期需要什么验证呢?当然,它必须是一个有效的日期,但格式呢?我们不会给用户任何指导。这显然是个问题。除此以外,日期应该是尚未到来的,而不是过去的。甚至还有一些日期应该禁止用户输入,比如非工作日。
该字段的另一个可用性问题就是用户不太可能轻松算出未来的日期。2周后是几号?难道我们向当前日期加14就行了么?如果那天已经超出了当前的月份就不对了。3周后的第一个周一是几号?如果没有日历,用户很难计算出想要的日期。
1.2.9 评论
我们来看看表单中最后一个字段——评论。用户可以随意输入一些评论来谈论他对我们服务的看法以及他喜欢的东西——或者是任何他想说的东西。
这是一个多行文本框,用户可以随心所欲地进行输入。其HTML如下所示。
<label for="comments">Comments:</label>
<textarea name="comments" rows="3" cols="35" id="comments">
</textarea>
这不是一个必填字段,所以无需进行验证。HTML表单元素<textarea>提供了一些基本的文字编辑功能。当用户输入到每行末尾时它会自动对单词进行续排。当用户输入的文本超出了文本域的表示范围,就会自动在右边出现一个滚动条,用户可以拖拽它进行滚动。这些是<textarea>的特性,但它缺少格式化功能。
至此我们完成了对该原始HTML表单的介绍。既然我们已经将该表单的诸多问题进行了分类,那我们就按照计划使用Dojo来逐一解决它们。
1.3 增强表单的计划
要解决我们遇到的所有问题需要做很多工作。我们需要为此订个计划,第一个任务就是对问题进行分类。我们将以最简单的改变开始,循序渐进地深入到复杂的问题中。下面列出的就是所有分类。每个分类对应到指南的一个步骤。
1. 在表单中引入Dojo
2. 增加客户端验证
3. 增加服务器端特性
4. 使用专门的Dojo widgets
5. 处理表单
在接下来的内容中会详细讲解每个主题。
1.3.1 在表单中引入Dojo
指南的第一步向你展示了如何将Dojo加到Web页面中,第一章会谈这个问题。
Dojo是一个函数库,可以通过编程或者声明的方式来使用它。我们可以通过编写JavaScript以编程的方式使用它,这会调用Dojo的函数,也可以通过使用HTML标记以声明的方式使用它。但在使用Dojo之前,我们必须将其加到页面中。换句话说,我们的Web页面必须要包含Dojo。这步操作不会解决我们遇到的任何问题,但没有它,我们将无法使用Dojo。
1.3.2 增加客户端验证
指南的第二步集中于客户端验证,第二章——“使用Dojo进行客户端验证”会谈到这个问题。
我们遇到的很多可用性问题都可以通过浏览器端的验证来解决。在这步中我们不考虑服务器端验证。一些开发者甚至没有想到可以用Ajax来解决这些问题,因为我们并没有创建服务器端请求。但这么说不太准确。毕竟Ajax有两面性。其一当然就是无需页面刷新的异步服务器通信,另一个却是通过JavaScript来处理显示以获得良好的交互性和视觉效果。
这步中我们要解决的一个问题就是必填字段的验证。在表单提交前我们使用JavaScript去检查数据,而不是先提交表单,然后让服务器端检查是否必填字段都已经填上了。这样应用看起来就会更快,因为用户无需等待服务器端响应就能发现非法数据。
1.3.3 增加服务器端特性
指南的第三步集中于经典的Ajax定义——无需刷新页面就能向服务器端发出请求。第三章“使用Dojo与服务器端协同工作”会谈到这个主题。
表单的其他问题是由提交整个页面来验证某些数据这个过程导致的。例如,服务器端需要检查用户名是否与已有的用户名冲突。这种情况下就没法避免服务器端验证了——因为数据就存放在服务器端。但我们不用请求一个新页面。我们可以创建一个仅检查用户名的Ajax请求,然后服务器端会返回这个验证信息,而不是一个新页面。这会很快而且无需打断用户的工作。
我们还会向服务器端发出请求以获得跟用户的输入有关的数据。例如,我们可以根据用户从下拉列表中选择的州名来从服务器端得到该州的城市列表。这步需要服务器端提供一些脚本来响应这些Ajax请求。我已经在服务器端创建了一些简单的JavaServer Page(JSP)脚本来做这件事。这些脚本非常简单,但足以说明指南中所讨论的那些特性了。
1.3.4 使用专门的Dojo widgets
指南的第四步谈到了强大的Dojo widgets中的一部分,这在第四章“使用Dojo widgets”会进行说明。
一些设计者喜欢用“Eye candy”这个词来描述很酷的可视化效果。Google Maps的拖拽至少算一个。Dojo不仅让我们可以增强现有的HTML表单元素,还提供了叫做widgets的新的可视化元素——提供了HTML不具备的新的表单元素。例如,服务日期的一个问题就是用户需要一个日历来选择日期。我们可以使用Dojo的日期选择widget,它可以在页面上显示一个日历。我们还可以用功能强大的富文本编辑器widget替换掉简单的<textarea>元素。
1.3.5 处理表单
指南的第五步也就是最后一步会讲解表单的处理和提交,第五章会讨论这个。
指南的最后一步解决了如何将表单元素当作一个整体的问题。我们会看到如何在表单提交前进行所有的客户端验证以及之后如何提交表单。我讨厌虎头蛇尾,但Dojo不会:Dojo会提交表单数据,就好象它是一个正常的HTML表单一样。换句话说,我们不用修改服务器端处理表单数据的组件。服务器甚至都不知道表单已被“Dojo化”了。这会减轻我们在服务器端的工作量。
1.4 获取并运行源代码
指南的每一步都在本书中得到了充分的讲解。然而,你可能想自己尝试一下。本指南的所有源代码都可从该书的Web站点上下载,其中包含了每一步开始时的代码以及最终代码。你可以下载开始时的代码,然后自己去修改,也可以下载每一步的最终代码并运行。
你可以使用任何喜欢的编辑器修改代码。对于一些步骤,甚至都不需要Web服务器。但这是一个Web应用,一些特性还是需要服务器的。我已经使用Java Server Pages(JSPs)创建了一些服务器端组件。这些组件对于运行示例是足够了,但我不建议也不推荐你将其用于产品系统中。
为了运行这些服务器端代码,你需要一个支持JSP的Web服务器。我推荐使用Tomcat,你可以从Apache软件基金会的站点1上下载。Tomcat是免费的。其实任何支持JSPs的Web服务器都可以。本书的Web站点也对这些代码的运行提供了帮助,同时还有一些勘误。请到该站点上找你想要的东西吧,如果有问题请随时联系我。(2)
1 你可从如下地址下载Tomcat Web服务器:http://tomcat.apache.org/。
2 该书的Web站点如下:http://www.objecttraininggroup.com/dojobook.
1.5 指南 步骤1——引入Dojo
该指南第一步的目的是让我们的Web页面可以使用Dojo Toolkit的函数。现在,我们可以将Dojo看作一个JavaScript文件,它需要包含到页面中(以及需要使用Dojo的每个页面中)。这很简单。Dojo Toolkit实际上包含了很多以目录结构组织的文件。我们在后续章节中将会看到这一点,但现在可以假设Dojo仅仅就是一个单独的JavaScript文件而已。
就像包含其他JavaScript文件一样,在我们的页面中也使用相同的方式来引入Dojo。我们使用<script>标记,稍候我会详解解释该标记。
1.5.1 下载或是创建源文件
在我们修改表单以包含<script>标记前,我们必须先创建表单。为了防止本书出版后可能会出现的任何问题,你可能想要看看本书的Web站点。你也可以在那下载这些源文件。你需要两个文件:“form.html”及“form.css”。每个文件的源代码也在这里列了出来。
下面是form本身的代码。该文件应命名为“form.html”。
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<!— Dojo Tutorial - Step 1 (form.html) —>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>Customer Entry Form</title>
<!— CSS —>
<link rel="stylesheet" href="form.css" type="text/css" />
</head>
<body>
<div class="formContainer">
<form action="submit.jsp" method="get" name="custForm">
<div class="formTitle">Customer Entry Form</div>
<div class="formRow">
<label for="firstName">First / Last Name: </label>
<input type="text" id="firstName" name="firstName" />
<input type="text" id="lastName" name="lastName" />
</div>
<div class="formRow">
<label for="userName">User Name: </label>
<input type="text" id="userName" name="userName" size="20" />
</div>
<div class="formRow">
<label for="email">Email: </label>
<input type="text" id="email" name="email" size="35" />
</div>
<div class="formRow">
<label for="address">Address: </label>
<input type="text" id="address" name="address" size="32"/>
</div>
<div class="formRow">
<label for="state">State:</label>
<select name="state" >
<option value="AL">Alabama</option>
<option value="AK">Alaska</option>
<option value="AZ">Arizona</option>
<option value="AR">Arkansas</option>
<option value="CA" selected="selected">California</option>
<option value="CO">Colorado</option>
<option value="CT">Connecticut</option>
<option value="DE">Delaware</option>
<option value="DC">District of Columbia</option>
<option value="FL">Florida</option>
<option value="GA">Georgia</option>
<option value="HI">Hawaii</option>
<option value="ID">Idaho</option>
<option value="IL">Illinois</option>
<option value="IN">Indiana</option>
<option value="IA">Iowa</option>
<option value="KS">Kansas</option>
<option value="KY">Kentucky</option>
<option value="LA">Louisiana</option>
<option value="ME">Maine</option>
<option value="MD">Maryland</option>
<option value="MA">Massachusetts</option>
<option value="MI">Michigan</option>
<option value="MN">Minnesota</option>
<option value="MS">Mississippi</option>
<option value="MO">Missouri</option>
<option value="MT">Montana</option>
<option value="NE">Nebraska</option>
<option value="NV">Nevada</option>
<option value="NH">New Hampshire</option>
<option value="NJ">New Jersey</option>
<option value="NM">New Mexico</option>
<option value="NY">New York</option>
<option value="NC">North Carolina</option>
<option value="ND">North Dakota</option>
<option value="OH">Ohio</option>
<option value="OK">Oklahoma</option>
<option value="OR">Oregon</option>
<option value="PA">Pennsylvania</option>
<option value="PR">Puerto Rico</option>
<option value="RI">Rhode Island</option>
<option value="SC">South Carolina</option>
<option value="SD">South Dakota</option>
<option value="TN">Tennessee</option>
<option value="TX">Texas</option>
<option value="UT">Utah</option>
<option value="VT">Vermont</option>
<option value="VA">Virginia</option>
<option value="WA">Washington</option>
<option value="WV">West Virginia</option>
<option value="WI">Wisconsin</option>
<option value="WY">Wyoming</option>
</select>
</div>
<div class="formRow">
<label for="city">City: </label>
<input id="city" name="city"/>
</div>
<div class="formRow">
<label for="zipCode">Zip Code: </label>
<input type="text" id="zipCode" name="zipCode" size="10" />
</div>
<div class="formRow">
<label for="serviceDate">Start Service:</label>
<input type="text" id="serviceDate" name="serviceDate" size="10"/>
</div>
<div class="formRow">
<label for="comments">Comments:</label>
<textarea name="comments" rows="3" cols="35" id="comments">
</textarea>
</div>
<input type="submit" value="Submit" id="submit" />
<input type="reset" id="reset" value="Cancel" />
</form>
</div>
</body>
</html>
该表单使用了一个CSS文件,这会提供一些简单的样式。这个CSS文件应命名为“form.css”,如下所示。
/* - - - - - - - - - - - - - - - - - - - - -
File : form.css
Description : Dojo Tutorial
Last Updated : March 1, 2008
- - - - - - - - - - - - - - - - - - - - -
*/
.formContainer {
margin: 2px auto;
background: #DBE4FF;
width: 500px;
border-width: 1px;
border-style: solid;
border-color: purple;
padding: 10px;
}
.formTitle {
font-size:24px; font-weight:bold;
padding: 10px;
}
form {
margin-top: 5px;
width: 480px;
}
.formRow {
position:relative;
padding: 4px 0.75em 2px 10em;
}
.formRow label {
position: absolute;
left: 0.75em;
float: none;
width: 10em;
display:block;
margin: 0;
}
1.5.2 引入Dojo Toolkit
现在我们需要在页面中引入Dojo Toolkit。通常我们要从Dojo的Web站点上下载源文件,将其放到我们自己的站点上,然后链接到它。但该指南的目标之一就是尽可能的简化,因此我们打算使用一个很酷的技术来链接到Internet上的Dojo源文件,而无需将其加到我们自己的Web服务器上。
AOL提供了一个叫做内容交付网络(CDN)的工具,这是一种面向Internet的“世界范围的地址边缘缓存(worldwide geographic edge caching)”的机制。它可以超快地从AOL服务器上将文件交付给Web用户,前提是这些文件的位置离服务器很近。这些文件还被压缩了,这又进一步提高了下载速度。AOL慷慨地向开发者和最终用户提供了该工具。请访问http://dev.aol.com/dojo来进一步了解AOL CDN和Dojo。
因此我们只需提供一个到AOL CDN上的Dojo文件的链接,而无需将其下载到我们的站点中。请在“form.html”的<head>标记中包含如下代码。同时请将这些代码放在</head>结束标记的末尾以与指南中的其他代码保持一致。
<script type="text/javascript"
src="http://o.aolcdn.com/dojo/1.1.0/dojo/dojo.xd.js"
djConfig="parseOnLoad: true"></script>
我还要多说几句。代码中提供的链接是针对本书出版时的Dojo版本。可能现在已经有新版本了。如果你想使用新版本的话,请登录本书的Web站点来查看源代码是否已经改变了。
你不必非得使用AOL CDN。你可以将Dojo下载到自己的服务器上。这可能是更好的做法,尤其在开发阶段。这样你就可以查看Dojo的源代码了,如果你不能上网还可以离线工作。
下载Dojo非常简单。你只需通过如下地址登录到Dojo的Web站点:http://www.dojotoolkit.org,然后点击下载链接。下载页面包含了当前版本和旧版本的链接。新版本可能会包含更多的特性,但这对于本指南的源代码来说不是必要的。请查看本书的Web站点以了解更新情况。
如果你选择下载Dojo,那么<script>标记中的链接就会不一样了。下面的代码片段假定你已经下载了Dojo的zip文件并将其解压缩到与form相同的目录下。
<script type="text/javascript"
src="dojo-release-1.1.0/dojo/dojo.js"
djConfig="parseOnLoad: true"></script>
属性djConfig=”parseOnLoad: true”的作用是告诉Dojo在页面的HTML中寻找你加入的任何Dojo widgets。为了做到这一点,我们需要引入Dojo parser。可以通过向页面中加入一些JavaScript代码来完成这项工作。在<head>标记中的<script>标记后加入如下代码以链接到Dojo。
<script type="text/javascript">
dojo.require("dojo.parser");
</script>
说明
上面包含“dojo.require”的代码必须跟在Dojo链接的后面,绝不能放在其前面——这非常重要。
1.5.3 引入Dojo样式表
在整个指南中,我们向页面中加入了各种各样的Dojo widgets。这些Dojo widgets的“样子”是通过样式定义的,而样式又是通过页面中引入的一些样式表来指定的。Dojo团队已经将widgets的“样子”放到单独的样式表中去定义了。这意味着你可以通过覆盖默认的样式来轻松地改变widgets的样式,使之符合你的站点的显示效果。你不必局限于widgets本身所带的那些样式。
第一个样式表“dojo.css”覆盖了标准的HTML页面元素的一些样式,如<body>、<div>及<form>。“dojo.css”中的内容并不多,其目的仅仅就是设置一些简单的样式而已。
下一个文件“tundra.css” 定义了很多标准Dojo widgets组件的样式。“tundra”主题是Dojo中三个内置主题之一。为什么叫tundra呢?Tundra是位于北极圈冰山下的寒冷且没有树木生长的地带。它充满了由苔藓和小灌木丛所形成的常年冻结的土壤。Dojo的“tundra”主题意在回忆那个单调的风景并对widgets提供最基本的修饰。“noir”主题更暗(“noir”是一个电影流派,强调真实性,因此经常拍成黑白电影)。“soria”主题明亮些(Soria是位于西班牙中北部地区的一个阳光明媚的城市)。
将下面的代码加到页面的<head>部分中以修饰我们的widgets,同时加入Dojo的tundra主题。顺序并不重要。
<style type="text/css">
@import "http://o.aolcdn.com/dojo/1.1.0/dojo/resources/dojo.css";
@import
"http://o.aolcdn.com/dojo/1.1.0/dijit/themes/tundra/tundra.css";
</style>
上面的代码仅仅将样式加到了页面中。现在我们必须将主题应用到页面上,这是通过向<body>标记增加一个class属性实现的。
<body class="tundra">
1.5.4 回顾所有的代码变化
我们已经对页面进行了大量修改,现在页面看起来是什么样子呢?可能大家都有点迷糊了。下面的代码就展示了页面的上半部分,你可以看到所有变化。
<!— Dojo Tutorial - Step 1 (form.html) —>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<!— Dojo Tutorial - Step 1 (form.html) —>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>Customer Entry Form</title>
<!— CSS —>
<link rel="stylesheet" href="../form.css" type="text/css" />
<!— CSS —>
<style type="text/css">
@import "../dojo-release-1.1.0/dojo/resources/dojo.css";
@import "../dojo-release-1.1.0/dijit/themes/tundra/tundra.css";
</style>
<link rel="stylesheet" href="../form.css" type="text/css" />
<script type="text/javascript"
src="../dojo-release-1.1.0/dojo/dojo.js.uncompressed.js"
djConfig="isDebug: true, debugAtAllCosts: true"></script>
<script type="text/javascript">
dojo.require("dojo.parser");
</script>
</head>
<body class="tundra">
一旦进行了所有这些修改,我们就可以运行新页面并查看其效果了。
1.5.5 运行新页面
新页面的运行效果如图1.4所示。
但愿你别太失望了——这个页面看起来与以前的几乎一样。我们虽然对样式进行了一些细微的改变,如标签和表单标题的字体,但也仅此而已了。这没问题。因为我们还没开始使用Dojo呢。我们仅仅在页面中添加了其引用。在下一章我们将继续指南的步骤2,在那里会实现客户端验证,到时候我们就会看到一些让人兴奋的效果了。
小结
我们通过一个指南开始了Dojo的探索之旅,该指南会讲解Dojo的一些基本特性。它包括5个步骤:
步骤1——引入Dojo(第一章)
步骤2——增加客户端验证(第二章)
步骤3——增加服务器端特性(第三章)
步骤4——使用专门的Dojo widgets(第四章)
步骤5——处理表单(第五章)
我们在本章通过实现指南的步骤1开始了Dojo的旅程——在HTML页面中引入了Dojo。
下一章将继续该指南。既然已经将Dojo加到了页面中,我们就可以使用它对表单中的字段进行客户端验证了。
同时,Dojo应用开发详解视频也将推出,敬请关注