5.4 小结

本章以 jQuery 对表单和表格的一些常用操作为例,介绍了从最基本的文本框得到和失去焦点到表单验证,从表格最基本的变色到筛选表格内容,最后还列举了选项卡,网页换肤等其他类型的应用。在实际开发中,相信这些案例也能为大家帮上大忙。

5.3 其他应用

5.3.1 网页字体大小

在某些网站经常有“放大”和“缩小”字号的控制按钮,通过单击它们,可以使网页的文字呈现不同的大小。

首先在空白的网页上添加两个字号控制按钮和一些文字,HTML代码如下:

[插图]

显示效果如图5-31所示。

[插图]

图5-31 网页初始化效果

当单击这两个按钮时可以分别控制文本字体的放大和缩小。因此,需要对“放大”按钮和“缩小”按钮进行相应的处理,代码如下:

[插图]

下面详细讲解以上代码所完成的操作。

[插图]

当文档加载完毕后,为所有的<span>元素绑定单击事件。

[插图]

获取 id 为“para”的元素的字体大小。获取的值是将返回的数字和单位,即16px。然后使用parseInt()方法去掉单位,因此16px就变成了16。parseInt()方法的第2个参数表示进制,代码中表示的是十进制。

[插图]

上面这段代码是获取单位,slice()方法返回字符串中从指定的字符开始的一个子字符串。因为这里使用的度量单位px是两个字符,所以指定字符串应该从倒数第2个字符开始。在后面再次设置字体大小时,就可以直接把单位拼接上。

[插图]

if语句用于判断当前被单击的<span>元素的class是否为“bigger”。如果是“bigger”,则需要为字体变量(textFontSize)增加 2px。如果单击的是“smaller”,则要为字体变量(textFontSize)减掉2px。

[插图]

最后,再次获取“para”元素并为它的font-size 属性赋予新的值(textFontSize),并且一定要拼接上单位。

如果发现无限放大和缩小不太合适,可以判断一下最小字体和最大字体,代码如下:

[插图]

显示效果如图5-32所示。

[插图]

图5-32 字体大小变化

5.3.2 网页选项卡

制作选项卡的原理比较简单,通过隐藏和显示来切换不同的内容。

与前面例子相同,首先构建HTML结构,代码如下:

[插图]

应用样式后,网页呈现效果如图5-33所示。

默认是选项卡的第1个选项被选中,然后下面区域显示相应的内容。例如图5-33所示,当单击“体育”选项卡时,“体育”选项卡将处于高亮状态,同时下面的内容也切换成“体育”了。当单击“娱乐”选项卡时,也显示相应的内容。下面将详细介绍实现选项卡的过程。

[插图]

图5-33 选项卡效果

首先需要为<li>元素绑定单击事件,代码如下:

[插图]

绑定事件后,需要将当前单击的<li>元素高亮,然后去掉其他同辈<li>元素的高亮。

[插图]

单击选项卡后,当前<li>元素处于高亮状态,而其他的<li>元素已去掉了高亮状态。但选项卡下面的内容还没被切换,因此需要将下面的内容也对应切换。显示效果如图5-34所示。

[插图]

图5-34 内容没被切换

从选项卡的基本结构可以知道,每个<li>元素都分别对应一个<div>区域。因此可以根据当前单击的<li>元素在所有<li>元素中的索引,然后通过索引来显示对应的区域,代码如下:

[插图]

这样,当单击<li>元素后,选项卡相应的内容也将切换,效果如图5-35所示。

[插图]

图5-35 对应的内容被切换

在上面的代码中,要注意$(“div.tab_box > div”)这个子选择器,如果用$(“div.tab_box div”)选择器,当子节点里再包含<div>元素的时候,就会引起程序错乱。因此获取当前选项卡下的子节点,才是这个例子所需要的。

至此制作选项卡的过程就完成了。如果读者还想加强些效果,例如光标滑入滑出效果,可以添加hover事件,代码如下:

[插图]

这样当光标滑过其他选项时,选项的样式会发生变化,如图5-36所示。

[插图]

图5-36 滑过“娱乐”选项

5.3.3 网页换肤

自从Web 2.0开始流行后,很多网站更加注重用户自定义,例如在网页上用户可以自定义新闻内容,可以任意拖动网页内容,也可以给网页选择一套自己喜欢的颜色等。

网页换肤的原理就是通过调用不同的样式表文件来实现不同皮肤的切换,并且需要将换好的皮肤记入Cookie中,这样用户下次访问时,就可以显示用户自定义的皮肤了。

首先设置HTML的结构,在网页中添加皮肤选择按钮(<li>元素)和基本内容,代码如下:

[插图]

然后根据 HTML 代码预定义几套换肤用的样式,分别有灰色、紫色、红色等 6套。默认是灰色。

注意:在设计HTML代码时,用了一些小技巧,就是将皮肤选择按钮
  • 元素的id与网页皮肤的样式文件名称设置的相同。这样就可以使完成换肤操作简化很多。
  • 然后为HTML代码添加样式,注意HTML结构要有一个带id的样式表链接,通过操作该链接的href属性的值,从而实现换肤。代码如下:

    [插图]

    运行后网页的初始化效果如图5-37所示。

    [插图]

    图5-37 初始化效果

    最后为皮肤选择按钮添加单击事件,有如下两个步骤。
    (1)当皮肤选择按钮被单击后,当前皮肤就被勾选。
    (2)将网页内容换肤。

    首先完成第1步,它与前面选项卡例子中高亮当前选项的代码相同,代码如下:

    [插图]

    然后完成第2步,即设置网页内容皮肤。前面为<link>元素设置的id,此时可以通过attr()方法为<link>元素的href属性设置不同的值,代码如下:

    [插图]

    完成后,当单击皮肤选择按钮时,就可以切换网页皮肤了,如图5-38所示,但是当用户刷新网页或者关闭浏览器后,皮肤又会被初始化,因此需要将当前选择的皮肤进行保存。

    [插图]

    图5-38 单击按钮后换肤

    在jQuery中有一款Cookie插件,它能简化Cookie的操作,此处就将其引入,代码如下:

    [插图]

    注意:Cookie插件的具体用法可以参考第7章。

    将当前皮肤保存进Cookie,代码如下:

    [插图]

    保存后,就可以通过Cookie来获取当前的皮肤了。如果Cookie确实存在,则将当前皮肤设置为Cookie记录的值,代码如下:

    [插图]

    完成的jQuery代码如下:

    [插图]

    此时,网页换肤功能不仅能正常切换,而且也能保存到Cookie中,当用户刷新网页后,仍然是当前选择的皮肤。

    在上面代码中,click事件中的函数内容与if (cookie_skin) { } 内的判断内容类似,只是有一个变量不同,因此可以通过给函数传递不同的参数,这样就可以多次调用(抽象化),代码如下:

    [插图]

    然后在单击事件和if (cookie_skin) { }内分别调用对应的参数:

    [插图]

    至此,网页换肤功能就完成了,效果如图5-39所示。

    [插图]

    图5-39 完成网页换肤

    5.2 表格应用

    在CSS技术之前,网页的布局基本都是依靠表格制作,当有了CSS之后,表格就被很多设计师所抛弃。但笔者认为,在进行网页布局时不能盲目地抛弃表格,在该用表格的时候,还要用表格。例如数据列表。用表格来显示非常适合。

    下面以表格中几个常用的应用作为示例来讲解。

    5.2.1 表格变色

    例如一张人员资料表,其HTML代码如下:

    [插图]

    应用样式后,显示效果如图5-19所示。

    [插图]

    图5-19 初始化效果

    这是一张非常普通的表格,现在需要给表格进行隔行变色操作。

    1.普通的隔行变色

    首先定义两个样式。

    CSS代码如下:

    [插图]

    然后选择表格奇数行和偶数行分别添加样式,可以使用选择器来完成,代码如下:

    [插图]

    显示效果如图5-20所示。

    [插图]

    图5-20 普通的隔行变色
    注意:$("tr:odd")和$("tr:even")选择器中索引是从0开始的,因此第1行是偶数。

    上面的代码会将表头也算进去,因此需要排除表格头部<thead>中的<tr>,将选择符改成如下代码:

    [插图]

    显示效果如图5-21所示。

    [插图]

    图5-21 表格隔行变色

    如果还需要将某一行变为高亮显示状态,那么可以使用contains选择器来实现。例如“王五”这行,代码如下:

    [插图]

    显示效果如图5-22所示。

    [插图]

    图5-22 高亮显示“王五”这行

    2.单选框控制表格行高亮

    在以上表格的基础上,在第1列前加上一列单选框,如图5-23所示。

    [插图]

    图5-23 带单选框的表格

    当单击某一行后,此行被选中高亮显示,并且单选框被选中。实现该过程需要以下几个步骤。
    (1)为表格行添加单击事件。
    (2)给单击的当前行添加高亮样式,然后将它的兄弟行的高亮样式去掉,最后将当前行里的单选框设置为选中。

    根据分析,可以写出如下jQuery代码:

    [插图]

    这样,就可以通过单击每行来实现表格行高亮,同时此行所在的单选框也被选中。

    上面代码中使用了end()方法,当前对象是$(this),当进行addClass(‘selected’)操作时,对象并未发生变化,当执行 siblings().removeClass(‘selected’)操作时,对象已经变为$(this).siblings(),因此后面的操作都是针对这个对象的,如果需要重新返回到$(this)对象,就可以使用end()方法,这样后面的

    [插图]

    操作就是:

    [插图]

    而不是:

    [插图]

    另外,初始化表格的时候,如果默认已经有单选框被选中,那么也需要处理,代码如下:

    [插图]

    这样当初始化表格的时候,默认已经选中的行将被高亮显示,如图5-24所示。

    [插图]

    图5-24 默认选中行被高亮显示
    注意:$('table :radio:checked').parent().parent().addClass('selected');是通过parent()方法逐步向父节点获取相应的元素的,也可以使用parents()方法直接获取:$('table:radio:checked').parents("tr").addClass('selected');此外,如果通过has选择器也可以进一步简化,表示含有选中的单选框的行将被高亮显示:$('tbody>tr:has(:checked)').addClass('selected');

    3.复选框控制表格行高亮

    复选框控制表格行与单选框不同,复选框能选择多行变色,并没有限制被选择的个数。当单击某行时,如果已经高亮了,则移除高亮样式并去掉当前行复选框的选中状态;如果还没高亮,则添加高亮样式并将当前行的复选框选中。

    判断是否已经高亮,可以使用hasClass()方法来完成。jQuery代码如下:

    [插图]

    显示效果如图5-25所示。

    [插图]

    图5-25 复选框控制行高亮

    此外,在不改变设计思路的前提下,上面的代码还可以再简化成如下代码:

    [插图]

    注意:在$(this)[hasSelected?"removeClass":"addClass"]('selected');中:[hasSelected?"removeClass":"addClass"]这是一个三元运算,结果为:"removeClass"或者"addClass"。因此$(this)[hasSelected?"removeClass":"addClass"]('selected');其实代表这2种情况:

    [插图]

    当用户刚进入页面时,也要处理已经被选中的表格行。jQuery代码如下:

    [插图]

    5.2.2 表格展开关闭

    在上例的人员表格的基础上,增加人员分类。

    HTML代码如下:

    [插图]

    显示效果如图5-26所示。

    [插图]

    图5-26 人员分类

    现在需要实现的是当单击分类行时,可以关闭相应的内容。例如单击“前台设计组”行,则它对应的“张山和李四”两行将收缩。

    在这个表格中,给每个<tr>元素设置属性是非常重要的,读者可以在HTML代码中看出一些规则,即给分类行设置了class=”parent”属性,同时也分别给它们设置了id值,而在它们下面的行,只设置了class属性,并且这个class的值是在id值的基础上通过加上“child_”来设置的。基于以上规则,jQuery实现代码如下:

    [插图]

    运行代码后,当单击表格的父行后,相应的子行会收缩,如图5-27所示。

    [插图]

    图5-27 单击某行,对齐的子行会收缩

    在图5-26 中,人员分类默认是展开的,如果当用户刚进入页面时,默认需要收缩起来,也是很简单的。只要触发click()事件即可。jQuery代码如下:

    [插图]

    5.2.3 表格内容筛选

    在前面的例子中,如果要高亮显示“王五”那一行,可以使用contains选择器来完成,代码如下:

    [插图]

    利用该选择器再结合jQuery的filter()筛选方法,可以实现表格内容的过滤。

    例如使用下面的jQuery代码就可以筛选出含有文本“李”的表格行。

    [插图]

    显示效果如图5-28所示。

    [插图]

    图5-28 筛选之后效果

    首先在表格上方添加一个文本框,用于根据用户输入的内容来筛选表格内容,然后为文本框绑定keyup事件,代码如下:

    [插图]

    最后将.filter(“:contains(‘李’)”)代码中的“李”用变量值代替,代码如下:

    [插图]

    当在文本框中输入“王”时,就会筛选出相应的表格行,显示效果如图5-29所示。

    [插图]

    图5-29 根据用户输入的文本来筛选

    注意表单元素有个特点,就是刷新网页后,其值会保持不变。例如在刚才筛选操作后,刷新网页,则会出现图5-30所示的现象,表单元素的值还存在,但表格内容已经被刷新了。

    [插图]

    图5-30 刷新后显示的表格数据

    要解决这个问题,只需要在 DOM 刚加载完时,为表单元素绑定事件并且立即触发该事件即可。

    [插图]

    这样,当页面被刷新后,就会立即执行id为“filterName”的keyup事件,因此表格内容就会保持刚才筛选出来的结果。

    第5章 jQuery对表单、表格的操作及更多应用

    通过前面4章的介绍和学习,读者已经对jQuery比较熟悉了,本章将通过讲解jQuery在表单(Form)和表格(Table)中的应用来加深对jQuery的理解。表单和表格都是HTML的重要组成部分,分别用于采集、提交用户输入的信息和显示列表数据。通过本章的实战锻炼,相信读者的jQuery技能又有一个极大的提高。

    5.1 表单应用

    一个表单有3个基本组成部分。
    (1)表单标签:包含处理表单数据所用的服务器端程序URL以及数据提交到服务器的方法。
    (2)表单域:包含文本框、密码框、隐藏域、多行文本框、复选框、单选框、下拉选择框和文件上传框等。
    (3)表单按钮:包括提交按钮、复位按钮和一般按钮,用于将数据传送到服务器上或者取消传送,还可以用来控制其他定义了处理脚本的处理工作。

    本节主要讲解jQuery在表单域中的应用。

    5.1.1 单行文本框应用

    文本框是表单域中最基本的元素,基于文本框的应用有很多。此处只简单介绍其中的一个应用—获取和失去焦点改变样式。

    首先,在网页中创建一个表单,HTML代码如下:

    [插图]

    应用样式后,初始化网页效果如图5-1所示。

    [插图]

    图5-1 初始化网页效果

    当文本框获取焦点后,它的颜色需要有变化;当它失去焦点后,则要恢复为原来的样式。此功能可以极大地提升用户体验,使用户的操作可以得到及时的反馈。可以使用CSS中的伪类选择符来实现以上的功能。

    CSS代码如下:

    [插图]

    但是IE 6并不支持除超链接元素之外的:hover伪类选择符,此时可以用jQuery来弥补I E6对CSS支持的不足。

    首先在CSS中添加一个类名为focus的样式。

    CSS代码如下:

    [插图]

    然后为文本框添加获取和失去焦点事件。

    jQuery代码如下:

    [插图]

    当文本框获得焦点时,会出现图5-2所示的效果。

    [插图]

    图5-2 文本框获取焦点

    经过处理后,在IE6下也可以呈现令人满意的效果。

    5.1.2 多行文本框应用

    1.高度变化

    例如某网站的评论框,如图5-3所示。

    [插图]

    图5-3 某网站评论框

    在图5-3的右上角,有“+(放大)”和“-(缩小)”的按钮,它们的功能就是用来控制评论框的高度的。例如单击“-”按钮,评论框的高度将会缩小,如图5-4所示。

    [插图]

    图5-4 评论框高度缩小

    评论框也需要设置最小高度和最大高度,当达到界限后再单击按钮,评论框的高度就不会再有任何变化。

    首先创建一个表单,其中包含评论框,HTML代码如下:

    [插图]

    然后需要思考以下两种情况。

    (1)当单击“放大”按钮后,如果评论框的高度小于500px,则在原有高度的基础上增加50px。

    [插图]

    图5-5 初始化网页效果

    (2)当单击“缩小”按钮后,如果评论框的高度大于50px,则在原有高度的基础上减去50px。

    jQuery代码如下:

    [插图]

    当单击“放大”或“缩小”按钮后,评论框就有了相应的变化,但此时评论框的变化效果很呆板,缺乏缓冲效果。在动画章节里,讲解过自定义动画方法animate(),此处可以将其中的一段代码:

    [插图]

    改为:

    [插图]

    因此,当单击“放大”按钮后,评论框的高度会在0.4秒内将增大50 px。

    注意在动画的过程中,需要判断评论框是否正处于动画,如果处于动画过程中,则不追加其他动画,以免造成动画队列不必要的累积,使效果出现问题。

    最终的jQuery代码为如下:

    [插图]

    此时评论框的高度变化具有一定的缓冲效果,比直接用height()方法的效果好多了。

    2.滚动条高度变化

    在多行文本框中,还有另外一个应用,就是通过控制多行文本框的滚动条的变化,使文本框里的内容滚动。

    与控制高度的方法相同,只不过此处需要控制的是另一个属性,即scrollTop。将以上代码改成如下:

    [插图]

    当单击“向上”或者“向下”按钮时,评论框的滚动条就会滚动到指定的位置,效果如图5-6所示。

    [插图]

    图5-6 通过控制scrollTop,使内容滚动

    5.1.3 复选框应用

    对复选框最基本的应用,就是对复选框进行全选、反选和全不选等操作。复杂的操作需要与选项挂钩,来达到各种级联反应效果。

    首先在空白网页中创建一个表单,其中放入一组复选框,HTML代码如下:

    [插图]

    如果需要使复选框处于选中或者不选状态,必须通过控制元素的checked属性来达到目的。如果属性checked的值为true,说明被选中;如果值为false,说明没被选中。因此可以基于这个属性来完成需求。

    [插图]

    图5-7 网页初始化呈现效果

    全选操作就是当用户单击“全选”按钮时,需要将复选框组全部选中。此时,需要为“全选”按钮绑定单击事件,然后使用选择符寻找符合要求的复选框,最后通过attr()方法来设置属性checked的值,使之选中。jQuery代码如下:

    [插图]

    全不选操作,只需要将复选框的checked属性的值设置为false,就可以实现,jQuery代码如下:

    [插图]

    反选操作稍微有些复杂,需要循环每一个复选框进行设置,取它们值的反值,即如果是true,就设置为false;如果是false,就设置为true,此种情况下可以使用非运算符“!”。

    使用下面的代码来实现反选操作:

    [插图]

    此处用jQuery的attr()方法来设置属性checked的有些复杂,如果改用JavaScript原生的DOM方法,将比创建jQuery对象更有效、简洁。

    简化后的代码为如下:

    [插图]

    复选框被选中后,用户单击“提交”按钮,需要将选中的项的值输出。可以通过val()方法获取选中的值。jQuery代码如下:

    [插图]

    单击“提交”按钮后,显示效果如图5-8所示。

    [插图]

    图5-8 选中输出

    此处不用按钮来控制复选框的全选与全不选,而用另一个复选框来控制,将按钮代码用一个复选框来代替,HTML代码如下:

    [插图]

    首先需要对另一个复选框控制,如图5-9所示。根据前面的功能代码,可以写出下面的代码:

    [插图]

    图5-9 对另一个复选框控制

    [插图]

    进一步观察思考后发现,所有复选框的checked属性的值和控制全选的复选框的checked属性的值是相同的,因此可以省略if判断,直接赋值,代码如下:

    [插图]

    当单击id为“CheckedAll”的复选框后,复选框组将被选中。当在复选框组里取消某一个选项的选中状态时,id 为“CheckedAll”的复选框并没有被取消选中状态,而此时需要它和复选框组能够联系起来,即复选框组里如果有一个或者更多没选中时,则取消id为“CheckedAll”的复选框的选中状态;如果复选框组都被选中时,则 id为“CheckedAll”的复选框也自动被选中。

    因此需要对复选框组进行操作,以通过它们来控制id为“CheckedAll”的复选框。具体实现思路如下。
    (1)对复选框组绑定单击事件。
    (2)定义一个flag变量,默认为true。
    (3)循环复选框组,当有没被选中的项时,则把变量flag的值设置为false。
    (4)根据变量flag的值来设置id为“CheckedAll”的复选框是否选中。
    ① 如果flag为true,说明复选框组都被选中。
    ② 如果flag为false,说明复选框组至少有一个未被选中。

    根据以上的思路,可以写出如下jQuery代码:

    [插图]

    此时id为“CheckedAll”的复选框和复选框组就可以联动起来了,如图5-10所示。

    除了上述的思路之外,也可以用下面的思路来实现。
    (1)对复选框组绑定单击事件。
    (2)判断复选框的总数是否与选中的复选框数量相等。

    [插图]

    图5-10 复选框和复选框组相互影响

    (3)如果相等,则说明全选中了,id为“CheckedAll”的复选框应当处于选中状态,否则不选中。

    根据提供的思路,可以写出如下jQuery代码:

    [插图]

    注意:在之前的jQuery版本中,都是使用attr()来访问对象的属性,比如取一个图片的alt属性,就可以这样做$('#img').attr('alt');但是在某些时候,比如访问input的disabled属性的时候,会有些问题。在有些浏览器里,只要写了 disabled 属性就可以,有些则要写:disabled ="disabled"。所以,从1.6版开始,jQuery提供新的方法prop()来获取这些属性。使用prop()的时候,返回值是标准属性:true/false,比如$('#checkbox').prop('disabled'),不会返回“disabled”或者“”,只会返回 true/false。当然赋值的时候也是如此。这样,便统一了所有操作,无论是从语法上还是语义上。那么,哪些属性应该用attr()访问,哪些应该用prop()访问呢?第一个原则:只添加属性名称该属性就会生效应该使用prop();第二个原则:只存在true/false的属性应该使用prop()。按照官方说明,如果是设置disabled和checked 这些属性,应使用prop()方法,而不是使用attr()方法。所以,在上例中,建议把所有attr()改成prop()。

    5.1.4 下拉框应用

    下拉框有非常多的应用,这里也只选择其中一个常用、典型的应用来进行介绍。

    图5-11是某网站的一个后台新增界面,在“负责频道”这个区域,用户可以通过中间的按钮将左边选中的选项添加到右边,也可以将右边的选项添加到左边,或者双击选项,将其添加给对方。

    [插图]

    图5-11 下拉框应用

    首先在网页中增加一左一右两个下拉框,然后在它们下方分别加上几个功能按钮。

    HTML代码如下:

    [插图]

    初始化后,网页效果如图5-12所示。

    [插图]

    图5-12 初始化效果

    需要实现的功能如下。
    (1)将选中的选项添加给对方。
    (2)将全部选项添加给对方。
    (3)双击某个选项将其添加给对方。

    首先实现第1个功能,即将下拉列表中被选中的选项添加给对方。

    首先要获取下拉列表中被选中的选项,然后将当前下拉列表中选中的选项删除,最后将删除的选项添加给对方。

    假设先将左边的选项添加到右边。jQuery代码如下:

    [插图]

    在前面的章节提到过,删除和追加这两个步骤可以用appendTo()方法直接完成,因此可以将上面代码简化如下:

    [插图]

    然后实现第2个功能,即将全部的选项添加给对方。

    将全部的选项添加给对方和将选中的选项添加给对方之间的惟一区别就是获取的对象不同,因此只要稍微修改代码就可以实现,jQuery代码如下:

    [插图]

    最后实现第3个功能,即双击某个选项将其添加给对方。

    首先给下拉列表绑定双击事件。

    jQuery代码如下:

    [插图]

    然后可以通过 $(“option:selected”,this)方法来获取被选中的选项,这样就可以完成第3个功能了,jQuery代码如下:

    [插图]

    前面3个功能都是将左边的选项添加给右边,如果要将右边的选项添加给左边,代码也完全相同,此处不再赘述。最终效果如图5-13所示。

    [插图]

    图5-13 最终效果

    5.1.5 表单验证

    表单作为HTML 最重要的一个组成部分,几乎在每个网页上都有体现,例如用户提交信息、用户反馈信息和用户查询信息等,因此它是网站管理者与浏览者之间沟通的桥梁。在表单中,表单验证的作用也是非常重要的,它能使表单更加灵活、美观和丰富。

    以一个简单的用户注册为例。首先新建一个表单,HTML代码如下:

    [插图]

    显示效果如图5-14所示。

    [插图]

    图5-14 表单初始化

    在表单内class属性为“required”的文本框是必须填写的,因此需要将它与其他的非必须填写表单元素加以区别,即在文本框后面追加一个红色的小星星标识。可以使用append()方法来完成,代码如下:

    [插图]

    显示效果如图5-15所示。

    [插图]

    图5-15 红色小星星标识

    当用户在“用户名”文本框中填写完信息后,将光标的焦点从“用户名”移出时,需要即时判断用户名是否符合验证规则。当光标的焦点从“邮箱”文本框移出时,需要即时判断“邮箱”填写是否正确,因此需要给表单元素添加失去焦点事件,即blur。jQuery代码如下:

    [插图]

    验证表单元素步骤如下。
    (1)判断当前失去焦点的元素是“用户名”还是“邮箱”,然后分别处理。
    (2)如果是“用户名”,判断元素的值的长度是否小于6,如果小于6,则用红色提醒用户输入不正确,反之,则用绿色提醒用户输入正确。
    (3)如果是“邮箱”,判断元素的值是否符合邮箱的格式,如果不符合,则用红色提醒用户输入不正确,反之,则用绿色提醒用户输入正确。
    (4)将提醒信息追加到当前元素的父元素的最后。

    根据以上分析,可以写出如下jQuery代码:

    [插图]

    当连续几次输入错误的格式后,会出现图5-16所示的效果。

    [插图]

    图5-16 操作多次的提示效果

    由于每次在元素失去焦点后,都会创建一个新的提醒元素,然后将它追加到文档中,最后就出现了多次的提醒信息。因此,需要在创建提醒元素之前,将当前元素以前的提醒元素都删除。可以使用remove()方法来完成,代码如下:

    [插图]

    显示效果如图5-17所示。

    [插图]

    图5-17 正确效果

    当鼠标在表单元素中多次失去焦点时,都可以提醒用户填写是否正确。但是,如果用户无视错误提醒,执意要单击“提交”按钮时,为了使表单填写准确,在表单提交之前,需要对表单的必须填写元素进行一次整体的验证。可以直接用trigger()方法来触发blur事件,从而达到验证效果。如果填写错误,就会以红色提醒用户;如果用户名和邮箱都不符合规则,那么就有两处错误,即有两个 class 为“onError”的元素,因此可以根据 class 为“onError”元素的长度来判断是否可以提交。如果长度为0,即true,说明已经可以提交了;如果长度大于0,即false,说明有错误,需要阻止表单提交。阻止表单提交可以直接用“returnfalse”语句。

    根据上面的分析,可以在提交事件中写出如下jQuery代码:

    [插图]

    显示效果如图5-18所示。

    [插图]

    图5-18 正确提交

    用户也许会提出:为什么每次都要等字段元素失去焦点后,才提醒输入是否正确?如果输入时就可以提醒,这样就可以更加即时了。

    为了达到用户提出的需求,需要给表单元素绑定keyup事件和focus事件,keyup事件能在用户每次松开按键时触发,实现即时提醒;focus事件能在元素得到焦点的时候触发,也可以实现即时提醒。

    代码如下:

    [插图]

    这样当用户将光标定位到文本框上和改变文本框的值时,表单就会即时提醒用户填写是否正确,从而符合了用户的需求。

    在前面的章节已经提过,trigger(“blur”)不仅会触发为元素绑定的blur事件,也会触发浏览器默认的blur事件,即不能将光标定位到文本框上。而triggerHandler(“blur”)只会触发为元素绑定的blur事件,而不触发浏览器默认的blur事件。

    至此,表单验证过程就全部完成。读者可以根据自己的实际需求修改验证规则。

    注意:客户端的验证仅用于提升用户操作体验,而服务器端仍需对用户输入的数据的合法性进行校验。对于禁用了脚本的用户和用户自制的网页提交操作,必须在服务器端验证。

    4.4 小结

    本章主要讲解了jQuery里的事件和动画。

    本章上半部分讲解的是 jQuery 中的事件。从最开始的页面装载讲起,在这个过程中,进一步介绍了 ready()方法;其次介绍了如何为元素绑定事件;接下来介绍了jQuery的两个自定义事件hover()方法和toggle()方法;然后通过例子来讲解事件冒泡和阻止默认操作;最后讲解了移除事件unbind()方法,模拟事件trigger()方法和bind()方法的其他用法。

    本章下半部分讲解的是jQuery中的动画。首先从最简单的动画方法show()和hide()方法开始介绍,通过带参数和不带参数两种方法来实现动画效果,参数可以使用速度关键字slow.fast和normal,也可以自己定义数字。接下来讲解了fadeIn()和fadeOut()方法,slideUp()和slideDown()方法,通过这些方法也能达到同样的动画效果。最后,介绍了最重要的一种方法即 animate()方法,通过此方法不仅能实现前面的所有动画,也能自定义动画。在做动画的过程中,需要特别注意动画的执行顺序,也要注意非动画方法会插队,可以通过动画方法的回调函数解决这个问题。

    本章最后通过某视频网站的动画效果,进一步加深了读者对事件和动画的了解。

    4.3 视频展示效果实例

    下面通过制作某视频网的视频展示效果,使读者对 jQuery的事件和动画效果有一个更为全面的了解。视频展示效果如图4-28所示。

    [插图]

    图4-28 视频展示效果

    用户可以单击左上角的左右箭头,来控制视频展示的左右滚动。当单击向右箭头时,下面的展示视频会向左滚动隐藏,同时新的视频展示会以滚动方式显示出来。在模拟这个效果之前,需要明确哪些是必须要做的。

    • 当视频展示内容处于最后一个版面的时候,如果再向后,则应该跳转到第一个版面。
    • 当视频展示内容处于第一个版面的时候,如果再向前,就应该跳转到最后一个版面。
    • 左上角的箭头旁边的蓝色圆点应该与动画一起切换,它代表着当前所处的版面。

    理清思路后,就可以开始动手制作这个效果。

    首先把页面结构设计好,可以把HTML结构简化成如下形式:

    [插图]

    最终实际页面的HTML代码如下:

    [插图]

    为页面的HTML代码应用CSS后,初始化页面如图4-29所示。

    [插图]

    图4-29 初始化页面

    接下来的工作是按照需求编写脚本,来控制页面的交互。

    首先通过jQuery选择器获取向右的箭头的元素,然后为它绑定click事件。

    因为“向右箭头”和“视频展示区域”在同一个祖先元素下,所以可以通过“向右箭头”来找到“视频展示区域”。首先获取“向右箭头”的祖先元素,然后在祖先元素下寻找“视频展示区域”。

    jQuery代码如下:

    [插图]

    找到相应的元素之后,就可以给相应的元素添加动画效果了。可以通过使用animate()方法控制“视频展示区域”的left样式属性的值来达到动画效果。很容易就可以获取left的值,left的值就等于每个版面的宽度。

    可以使用width()方法来获取每个版面的宽度,代码如下:

    [插图]

    完成这一步后,此时的代码如下:

    [插图]

    现在的问题是如何知道动画已经到达最后一版。

    “视频展示区域”每个版面摆放了4张视频图片,如果能够获取到视频图片的总数,然后用总数除以4就可以得到总的版面数。例如总共有8张视频图片,那么就是2个版面;如果有12张视频图片,那么就是3个版面;如果只有9张视频图片,则必须把小数向上舍入,即3个版面。在还没有到达最后一个版面之前,需要在当前版面数的基础上加1,当到达最后一个版面时(即当前的版面数等于总的版面数),则需要把当前的版面数设置为1,使之重新开始动画效果。

    • 首先初始化当前的版面数为1,即第1个版面:

    [插图]

    然后根据刚才的分析,写出如下代码:

    [插图]

    这一步完成后,还需要使左上角的箭头旁边的蓝色圆点跟随动画一起切换,来标识当前所处的版面。只需要把样式“current”添加到代表当前版面的“蓝色圆点”上就可以了。

    如果想知道当前的版面数,方法很简单,其实前面的代码已经完成了这个任务,变量page的值就是版面数。由于eq()方法的下标是从0开始,因此只要把page减去1就可得到当前的版面数,然后使用下面的代码来标识当前版面:

    [插图]

    此时,把代码整合,如下所示:

    [插图]

    运行上面的代码,慢慢地单击向右按钮,并没有发现任何问题,但是如果快速地单击“向右”按钮,就会出现问题了:放开光标,图片还在滚动。

    在前面已经介绍过动画队列,这里的问题就是由动画队列引起的。当快速单击“向右”按钮时,单击产生的动画会追加到动画队列中,从而出现放开光标之后,图片还在继续滚动的情况。

    为了解决这个问题,可以在动画方法外围加一段判断元素是否处于动画状态的代码,如下所示:

    [插图]

    如果不处于动画,则给它添加下一个动画。

    最终的jQuery代码如下:

    [插图]

    运行代码后,单击“向右”按钮,效果一切正常。此时已经把“向右”按钮的交互效果完成了。“向左”按钮的交互代码与“向右”按钮类似,区别是在当前的版面数已经为第1版时,如果再往前,则需要把版面跳转到最后一个版面,操作代码如下:

    [插图]

    此时,效果就完成了,“向右”和“向左”按钮都可以单击,动画效果也能正常运行,并且当前版面也能被标识。效果如图4-30所示。

    [插图]

    图4-30 动画效果
    注意:JavaScript的动画效果跟CSS密不可分,在上例中,为元素设置合适的CSS属性也至关重要,比如,我们为“v_content”设置了overflow:hidden; position: relative;,而后为它的子元素设置了position:absolute;。

    4.2 jQuery中的动画

    动画效果也是jQuery库吸引人的地方。通过jQuery的动画方法,能够轻松地为网页添加非常精彩的视觉效果,给用户一种全新的体验。

    4.2.1 show()方法和hide()方法

    1.show()方法和hide()方法

    show()方法和hide()方法是 jQuery 中最基本的动画方法。在 HTML 文档里,为一个元素调用hide()方法,会将该元素的display样式改为“none”。例如,使用如下代码隐藏element元素。

    [插图]

    这段代码的功能与用css()方法设置display属性效果相同:

    [插图]

    当把元素隐藏后,可以使用show()方法将元素的display样式设置为先前的显示状态(“block”或“inline”或其他除了“none”之外的值)。

    jQuery代码如下:

    [插图]

    在前面的例子中,已经多次使用hide()方法和show()方法,通过这两种方法可以控制“内容”的显示和隐藏。

    jQuery代码如下:

    [插图]

    注意hide()方法在将“内容”的display属性值设置为“none”之前,会记住原先的display属性值(“block”或“inline”或其他除了“none”之外的值)。当调用show()方法时,就会根据hide()方法记住的display属性值来显示元素。

    在本例中,“内容”的display 属性的值是“block”,当单击“标题”链接执行 hide()方法的时候,hide()方法会做两步动作,首先会记住“内容”的display属性的值“block”,然后把display属性的值设置为“none”。

    在Firebug工具中DOM结构显示效果如图4-21所示。

    [插图]

    图4-21 执行hide()方法

    当执行show()方法的时候,“内容”的display属性的值就会被还原为调用hide()方法前的状态。

    在Firebug工具中DOM结构显示效果如图4-22所示。

    [插图]

    图4-22 执行show()方法
    注意:用 jQuery做动画效果要求要在标准模式下,否则可能会引起动画抖动。标准模式即要求文件头部包含如下的DTD定义:``

    2.show()方法和hide()方法让元素动起来

    show()方法和hide()方法在不带任何参数的情况下,相当于css(“display”,”none/block/inline”),作用是立即隐藏或显示匹配的元素,不会有任何动画。如果希望在调用show()方法时,元素慢慢地显示出来,可以为show()方法指定一个速度参数,例如,指定一个速度关键字“slow”。jQuery代码如下:

    [插图]

    运行该代码后,元素将在600毫秒内慢慢地显示出来。其他的速度关键字还有“normal”和“fast”(长度分别是400毫秒和200毫秒)。

    不仅如此,还可以为显示速度指定一个数字,单位是毫秒。

    例如,使用如下代码使元素在1秒钟(1000毫秒)内显示出来:

    [插图]

    类似的,以下代码将使元素在1秒钟(1000毫秒)内隐藏:

    [插图]

    在前面的例子中,把其中的hide()方法改为hide(600),show()方法改为show(600)。jQuery代码如下:

    [插图]

    运行该代码后,当单击“标题”链接时,“内容”已经产生动画了。效果如图4-23所示。

    [插图]

    图4-23 hide(600)方法执行效果过程

    从代码执行过程中,可以发现,hide(600)方法会同时减少“内容”的高度、宽度和不透明度,直至这3个属性的值都为0,最后设置该元素的CSS规则为“display:none”。同理,show(600)方法则会从上到下增大“内容”的高度,从左到右增大“内容”的宽度,同时增加“内容”的不透明度,直至新闻内容完全显示。

    4.2.2 fadeIn()方法和fadeOut()方法

    与show()方法不相同的是,fadeIn()方法和fadeOut()方法只改变元素的不透明度。fadeOut()方法会在指定的一段时间内降低元素的不透明度,直到元素完全消失(“display: none”)。fadeIn()方法则相反。

    在上个例子中,如果只想改变“内容”的不透明度,就可以使用fadeOut()方法。

    jQuery代码如下:

    [插图]

    当第1 次单击“标题”链接后,“内容”慢慢地消失了(淡出),当再次单击“标题”链接后,“内容”又慢慢地显示了(淡入),效果如图4-24所示。

    [插图]

    图4-24 段落元素淡化效果

    4.2.3 slideUp()方法和slideDown()方法

    slideUp()方法和slideDown()方法只会改变元素的高度。如果一个元素的display属性值为“none”,当调用 slideDown()方法时,这个元素将由上至下延伸显示。slideUp()方法正好相反,元素将由下到上缩短隐藏。使用 slideUp()方法和slideDown()方法再次对“内容”的显示和隐藏方式进行改变,代码如下:

    [插图]

    实现效果如图4-25所示。

    [插图]

    图4-25 “内容”正在向下展开显示
    注意:jQuery中的任何动画效果,都可以指定3种速度参数,即“slow”、“normal”和“fast”(时间长度分别是0.6秒、0.4秒和0.2秒)。当使用速度关键字时要加引号,例如show("slow"),如果用数字作为时间参数时就不需要加引号,例如show(1000)。

    4.2.4 自定义动画方法animate()

    前面已经讲了3种类型的动画。其中show()方法和hide()方法会同时修改元素的多个样式属性,即高度、宽度和不透明度;fadeOut()方法和fadeIn()方法只会修改元素的不透明度;slideDown()方法和slideUp()方法只会改变元素的高度。

    很多情况下,这些方法无法满足用户的各种需求,那么就需要对动画有更多的控制,需要采取一些高级的自定义动画来解决这些问题。在jQuery中,可以使用animate()方法来自定义动画。其语法结构为:

    [插图]

    参数说明如下。

    (1)params:一个包含样式属性及值的映射,比如{property1:“value1”,property2: “value2”,…}。
    (2)speed:速度参数,可选。
    (3)callback:在动画完成时执行的函数,可选。

    1.自定义简单动画

    前面的几个例子,从不同的方面使元素动了起来,animate()方法也可以使元素动起来,而且animate()方法更具有灵活性。通过animate()方法,能够实现更加精致新颖的动画效果。

    首先来看一个简单例子,有一个空白的HTML文档,里面有一个id=”panel”的<div>元素,当<div>元素被单击后,能在页面上横向飘动。

    先给这个<div>元素添加CSS样式。

    [插图]

    此时页面的初始化效果如图4-26所示。

    [插图]

    图4-26 网页初始化效果

    为了使这个元素动起来,要更改元素的“left”样式属性。需要注意的是在使用animate()方法之前,为了能影响该元素的“top”、“left”、“bottom”和“right”样式属性,必须先把元素的position样式设置为“relative”或者“absolute”。本例中,设置的是“position:relative”,有了这个值,就可以调整元素的left属性,使元素动起来。

    现在,添加如下jQuery代码:

    [插图]

    在本段代码中,首先为id为“panel”的元素创建一个单击事件,然后对元素加入animate()方法,使元素在3秒(3000毫秒)内,向右移动500像素。运行效果如图4-27所示。

    [插图]

    图4-27 `
    `元素右移500像素

    2.累加、累减动画

    在之前的代码中,设置了{left: “500px”}作为动画参数。如果在500px之前加上“+=”或者“- =”符号即表示在当前位置累加或者累减。代码如下:

    [插图]

    3.多重动画

    (1)同时执行多个动画

    在上面的例子中,通过控制属性left的值实现了动画的效果,这是一个很单一的动画。如果需要同时执行多个动画,例如在元素向右滑动的同时,放大元素的高度。根据animate()方法的语法结构,可以写出如下的jQuery代码:

    [插图]

    运行代码后,<div>元素在向右滑动的同时,也会放大高度。

    (2)按顺序执行多个动画

    上例中,两个动画效果(left:”500px”和height:”200px”)是同时发生的,如果想要按顺序执行动画,例如让<div>元素先向右滑动,然后再放大它的高度,只需把代码拆开,然后按照顺序写就可以了,jQuery代码如下:

    [插图]

    因为animate()方法都是对同一个jQuery对象进行操作,所以也可以改为链式的写法,代码如下:

    [插图]

    这样一来,就满足上文提出的需求了。在“left”这个定位属性改变之前,“height”属性将不会被改变。像这样,动画效果的执行具有先后顺序,称为“动画队列”。

    4.综合动画

    接下来将完成更复杂的动画。单击<div>元素后让它向右移动的同时增大它的高度,并将它的不透明度从50%变换到100%,然后再让它从上到下移动,同时它的宽度变大,当完成这些效果后,让它以淡出的方式隐藏。

    实现这些功能的jQuery代码如下:

    [插图]

    运行代码后,动画效果一步步执行完毕。通过这个例子可以看出,为同一元素应用多重效果时,可以通过链式方式对这些效果进行排队。

    4.2.5 动画回调函数

    在上例中,如果想在最后一步切换元素的CSS样式,而不是隐藏元素:

    [插图]

    如果只是按照常规的方式,将fadeOut (“slow”) 改为css (“border”,”5px solidblue”)

    这样并不能得到预期效果。预期的效果是在动画的最后一步改变元素的样式,而实际的效果是,刚开始执行动画的时候,css()方法就被执行了。

    出现这个问题的原因是 css()方法并不会加入到动画队列中,而是立即执行。可以使用回调函数(callback)对非动画方法实现排队。只要把 css()方法写在最后一个动画的回调函数里即可。代码如下:

    [插图]

    这样一来,css()方法就加入到动画队列中了,从而满足了上文提出的需求。

    注意:callback回调函数适用于jQuery所有的动画效果方法,例如slideDown()方法的回调函数:

    [插图]

    这段代码表示id = “element”的元素将在0.4秒内(正常速度)向下完全展开。当动画完成后,执行回调函数体内的代码。

    4.2.6 停止动画和判断是否处于动画状态

    1.停止元素的动画

    很多时候需要停止匹配元素正在进行的动画,例如上例的动画,如果需要在某处停止动画,需要使用stop()方法。stop()方法的语法结构为:

    [插图]

    参数clearQueue和gotoEnd都是可选的参数,为Boolean值(ture或flase)。clearQueue代表是否要清空未执行完的动画队列,gotoEnd代表是否直接将正在执行的动画跳转到末状态。

    如果直接使用stop()方法,则会立即停止当前正在进行的动画,如果接下来还有动画等待继续进行,则以当前状态开始接下来的动画。经常会遇到这种情况,在为一个元素绑定hover事件之后,用户把光标移入元素时会触发动画效果,而当这个动画还没结束时,用户就将光标移出这个元素了,那么光标移出的动画效果将会被放进队列之中,等待光标移入的动画结束后再执行。因此如果光标移入移出得过快就会导致动画效果与光标的动作不一致。此时只要在光标的移入、移出动画之前加入stop()方法,就能解决这个问题。stop()方法会结束当前正在进行的动画,并立即执行队列中的下一个动画。以下代码就可以解决刚才的问题。

    [插图]

    如果遇到组合动画,例如:

    [插图]

    此时只用一个不带参数的stop()方法就显得力不从心了。因为stop()方法只会停止正在进行的动画,如果动画正执行在第1阶段(改变height的阶段),则触发光标移出事件后,只会停止当前的动画,并继续进行下面的animate({width : “300” } ,300) 动画,而光标移出事件中的动画要等这个动画结束后才会继续执行,这显然不是预期的结果。这种情况下stop()方法的第1个参数就发挥作用了,可以把第1个参数(clearQueue)设置为true,此时程序会把当前元素接下来尚未执行完的动画队列都清空。把上面的代码改成如下代码,就能实现预期的效果。

    [插图]

    第2个参数(gotoEnd)可以用于让正在执行的动画直接到达结束时刻的状态,通常用于后一个动画需要基于前一个动画的末状态的情况,可以通过stop(false,true)这种方式来让当前动画直接到达末状态。

    当然也可以两者结合起来使用 stop(true,true),即停止当前动画并直接到达当前动画的末状态,并清空动画队列。

    注意,jQuery只能设置正在执行的动画的最终状态,而没有提供直接到达未执行动画队列最终状态的方法。例如有一组动画:

    [插图]

    无论怎么设置stop()方法,均无法在改变“width”或者“height”时,将此<div>元素的末状态变成300 × 150的大小,并且设置透明度为0.2。

    2.判断元素是否处于动画状态

    在使用animate()方法的时候,要避免动画积累而导致的动画与用户的行为不一致。当用户快速在某个元素上执行 animate()动画时,就会出现动画积累。解决方法是判断元素是否正处于动画状态,如果元素不处于动画状态,才为元素添加新的动画,否则不添加。代码如下:

    [插图]

    这个判断方法在animate()动画中经常被用到,需要特别注意。

    3.延迟动画

    在动画执行的过程中,如果想对动画进行延迟操作,那么可以使用delay()方法,使用方式如下:

    [插图]

    delay()方法允许我们将队列中的函数延时执行。它既可以推迟动画队列中函数的执行,也可以用于自定义队列。

    4.2.7 其他动画方法

    除了上面提到的动画方法,jQuery中还有4个专门用于交互的动画方法。

    • toggle( speed, [callback] )
    • slideToggle( speed, [ easing ], [callback] )
    • fadeTo( speed, opacity, [callback] )
    • fadeToggle ( speed, [ easing ], [callback] )

    1.toggle()方法

    toggle()方法可以切换元素的可见状态。如果元素是可见的,则切换为隐藏的;如果元素是隐藏的,则切换为可见的。

    给“内容”添加toggle()事件,代码如下:

    [插图]

    当单击“标题”链接后,“内容”会在可见和隐藏两种状态之间切换。

    相当于以下jQuery代码:

    [插图]

    2.slideToggle()方法

    slideToggle()方法通过高度变化来切换匹配元素的可见性。这个动画效果只调整元素的高度。

    给“内容”添加slideToggle()事件,代码如下:

    [插图]

    当单击“标题”链接后,“内容”会在可见和隐藏两种状态之间切换,不过是通过改变元素的高度来实现的。

    相当于以下jQuery代码:

    [插图]

    3.fadeTo()方法

    fadeTo()方法可以把元素的不透明度以渐进方式调整到指定的值。这个动画只调整元素的不透明度,即匹配的元素的高度和宽度不会发生变化。

    给“内容”添加fadeTo()事件,代码如下:

    [插图]

    当“标题”链接被单击后,“内容”会渐渐地调整到指定的不透明度(20%)。

    4.fadeToggle()方法

    fadeToggle()方法通过不透明度变化来切换匹配元素的可见性。这个动画效果只调整元素的不透明度。

    给“内容”添加fadeToggle()事件,代码如下:

    [插图]

    相当于以下jQuery代码:

    [插图]

    4.2.8 动画方法概括

    从基本动画方法hide()和show()到fadeIn()和fadeOut(),然后到slideUp()和slideDown(),再到自定义动画方法animate(),最后到交互动画方法toggle()、slideToggle(),fadeTo()和fadeToggle()。在介绍了如此多的动画方法后,现总结概括如下。

    1.改变样式属性

    表4-1 动画方法说明

    [插图]

    需要特别注意animate()方法,可以使用它来替代其他所有的动画方法。

    • 用animate()方法代替show()方法:

    [插图]

    等价于:

    [插图]

    • 用animate()方法代替fadeIn()方法:

    [插图]

    等价于:

    [插图]

    • 用animate()方法代替slideDown()方法:

    [插图]

    等价于:

    [插图]

    • 用animate()方法代替fadeTo()方法:

    [插图]

    等价于:

    [插图]

    事实上,这些动画就是 animate()方法的一种内置了特定样式属性的简写形式。在animate()方法中,这些特定样式的属性值可以为“show”、“hide”和“toggle”,也可以是自定义数字(值)。

    2.动画队列

    (1)一组元素上的动画效果

    • 当在一个animate()方法中应用多个属性时,动画是同时发生的。
    • 当以链式的写法应用动画方法时,动画是按照顺序发生的。

    (2)多组元素上的动画效果

    • 默认情况下,动画都是同时发生的。
    • 当以回调的形式应用动画方式时,动画是按照回调顺序发生的。

    另外,在动画方法中,要注意其他非动画方法会插队,例如 css()方法要使非动画方法也按照顺序执行,需要把这些方法写在动画方法的回调函数中。

    第4章 jQuery中的事件和动画

    JavaScript和HTML之间的交互是通过用户和浏览器操作页面时引发的事件来处理的。当文档或者它的某些元素发生某些变化或操作时,浏览器会自动生成一个事件。例如当浏览器装载完一个文档后,会生成事件;当用户单击某个按钮时,也会生成事件。虽然利用传统的JavaScript事件能完成这些交互,但jQuery增加并扩展了基本的事件处理机制。jQuery不仅提供了更加优雅的事件处理语法,而且极大地增强了事件处理能力。

    4.1 jQuery中的事件

    4.1.1 加载DOM

    以浏览器装载文档为例,在页面加载完毕后,浏览器会通过JavaScript为DOM元素添加事件。在常规的JavaScript 代码中,通常使用 window.onload 方法,而在jQuery 中,使用的是$(document).ready()方法。$(document).ready()方法是事件模块中最重要的一个函数,可以极大地提高 Web 应用程序的响应速度。jQuery就是用$(document).ready()方法来代替传统 JavaScript的window.onload 方法的。通过使用该方法,可以在 DOM 载入就绪时就对其进行操纵并调用执行它所绑定的函数。在使用过程中,需要注意$(document).ready()方法和window.onload方法之间的细微区别。

    1.执行时机

    $(document).ready()方法和window.onload 方法有相似的功能,但是在执行时机方面是有区别的。window.onload 方法是在网页中所有的元素(包括元素的所有关联文件)完全加载到浏览器后才执行,即JavaScript此时才可以访问网页中的任何元素。而通过jQuery中的$(document).ready()方法注册的事件处理程序,在DOM完全就绪时就可以被调用。此时,网页的所有元素对jQuery而言都是可以访问的,但是,这并不意味着这些元素关联的文件都已经下载完毕。

    举一个例子,有一个大型的图库网站,为网页中所有图片添加某些行为,例如单击图片后让它隐藏或显示。如果使用window.onload方法来处理,那么用户必须等到每一幅图片都加载完毕后,才可以进行操作。如果使用jQuery中的$(document).ready()方法来进行设置,只要DOM就绪就可以操作了,不需要等待所有图片下载完毕。很显然,把网页解析为DOM树的速度比把页面中的所有关联文件加载完毕的速度快很多。

    另外,需要注意一点,由于在$(document).ready()方法内注册的事件,只要DOM 就绪就会被执行,因此可能此时元素的关联文件未下载完。例如与图片有关的HTML下载完毕,并且已经解析为DOM树了,但很有可能图片还未加载完毕,所以例如图片的高度和宽度这样的属性此时不一定有效。要解决这个问题,可以使用jQuery中另一个关于页面加载的方法—load()方法。load()方法会在元素的onload事件中绑定一个处理函数。如果处理函数绑定给window对象,则会在所有内容(包括窗口、框架、对象和图像等)加载完毕后触发,如果处理函数绑定在元素上,则会在元素的内容加载完毕后触发。jQuery代码如下:

    [插图]

    等价于JavaScript中的以下代码:

    [插图]

    2.多次使用

    第一章曾经用一个表格(表1-2)总结过windows.onload方法和$(document).ready()方法的区别,现在进行详细讲解。

    假设网页中有两个函数,JavaScript代码如下:

    [插图]

    当网页加载完毕后,通过如下JavaScript代码来分别调用one函数和two函数:

    [插图]

    然而当运行代码后,发现只弹出字符串“two”对话框,如图4-1所示。

    [插图]

    图4-1 弹出字符串“two”对话框

    字符串“one”对话框不能被弹出的原因是 JavaScript的onload 事件一次只能保存对一个函数的引用,它会自动用后面的函数覆盖前面的函数,因此不能在现有的行为上添加新的行为。

    为了达到两个函数顺序触发的效果,只能再创建一个新的JavaScript 方法来实现,Javascript代码如下:

    [插图]

    虽然这样编写代码能解决某些问题,但还是不能满足某些需求,例如有多个JavaScript文件,每个文件都需要用到window.onload方法,这种情况下用上面提到的方法编写代码会非常麻烦。而jQuery的$(document).ready()方法能够很好地处理这些情况,每次调用$(document).ready()方法都会在现有的行为上追加新的行为,这些行为函数会根据注册的顺序依次执行。例如如下jQuery代码:

    [插图]

    运行代码后,会先弹出字符串“one”对话框,然后弹出字符串“two”对话框,依次显示图4-2和图4-3所示的效果。

    [插图]

    图4-2 弹出字符串“one”对话框

    [插图]

    图4-3 弹出字符串“two”对话框

    3.简写方式

    如果读者注意过本书前几章的例子,会发现例子中并不是用的下面的代码:

    [插图]

    而是用的下面的代码:

    [插图]

    后者是前者的简写方式。

    另外,$(document)也可以简写为$()。当$()不带参数时,默认参数就是“document”,因此可以简写为:

    [插图]

    3种方式都是一样的功能,读者可以根据自己的喜好,选择其中的一种。

    4.1.2 事件绑定

    在文档装载完成后,如果打算为元素绑定事件来完成某些操作,则可以使用bind()方法来对匹配元素进行特定事件的绑定,bind()方法的调用格式为:

    [插图]

    bind()方法有3个参数,说明如下。

    第1个参数是事件类型,类型包括:blur、focus、load、resize、scroll、unload、click、dblclick、mousedown、mouseup、mousemove、mouseover、mouseout、mouseenter、mouseleave、change、select、submit、keydown、keypress、keyup和error等,当然也可以是自定义名称。

    第2个参数为可选参数,作为event.data属性值传递给事件对象的额外数据对象。

    第3个参数则是用来绑定的处理函数。

    注意:可以发现,jQuery中的事件绑定类型比普通的JavaScript事件绑定类型少了“on”。例如鼠标单击事件在jQuery中对应的是click()方法,而在JavaScript中对应的是onclick()。

    1.基本效果

    下面通过一个示例来了解bind()方法的用法。

    假设网页中有一个FAQ,单击“标题”链接将显示内容。

    HTML代码如下:

    [插图]

    应用CSS样式表后,网页效果图如图4-4所示。

    [插图]

    图4-4 网页初始化效果图

    按照需求,需要完成以下几个步骤。
    (1)等待DOM装载完毕。
    (2)找到“标题”所在的元素,绑定click事件。
    (3)找到“内容”元素,将“内容”元素显示。

    根据分析的步骤,可以轻易地写出如下jQuery代码:

    [插图]

    运行代码,单击“标题”链接,“内容”就展开了,效果如图4-5所示。

    [插图]

    图4-5 显示内容

    在上面的例子中,为“标题”绑定了一个click事件,单击标题链接后,显示“内容”。

    与ready()方法一样,bind()方法也可以多次调用。

    上面jQuery代码中有一个关键字this,与在JavaScript中的作用一样,this引用的是携带相应行为的DOM元素。为了使该DOM元素能够使用jQuery中的方法,可以使用$(this)将其转换为jQuery对象(具体实现方法参见第1章1.4.2小节jQuery对象和DOM对象的相互转换)。

    2.加强效果

    在上面的例子中,单击“标题”显示出“内容”;再次单击“标题”,“内容”并没有任何反应。现在需要加强效果:第2次单击“标题”,“内容”隐藏;再次单击“标题”,“内容”又显示,两个动作循环出现。为了实现这个功能,需要经过以下几个步骤。
    (1)等待DOM装载完毕。
    (2)找到“标题”所在的元素,绑定click事件。
    (3)找到“内容”元素,如果“内容”元素是显示的,则隐藏,如果“内容”元素是隐藏的,则显示。

    加强效果的第
    (3)步需要做判断,原理如下:

    [插图]

    为了判断元素是否显示,可以使用jQuery中的is()方法来完成。jQuery代码如下:

    [插图]

    在代码中,发现$ (this).next () 被多次使用,因此可以为它定义一个局部变量:

    [插图]

    然后把局部变量引入到代码中,改进后的jQuery代码如下:

    [插图]

    通过以上的修改,可以实现加强效果。当反复地单击“标题”链接时,“内容”会在隐藏和显示两种状态下切换。

    注意:当发现相同的选择器在你的代码里出现多次时,请用变量把它缓存起来。更多 jQuery性能优化请参考附录。

    3.改变绑定事件的类型

    上面的例子中,给元素绑定的事件类型是 click,当用户单击的时候会触发绑定的事件,然后执行事件的函数代码。现在把事件类型换成mouseover和mouseout,即当光标滑过的时候,就触发事件。需要进行以下几步操作。
    (1)等待DOM装载完毕。
    (2)找到“标题”所在的元素,绑定mouseover事件。
    (3)找到“内容”元素,显示“内容”。
    (4)找到“标题”所在的元素,绑定mouseout事件。
    (5)找到“内容”元素,隐藏“内容”。

    根据分析的步骤,可以写出如下jQuery代码:

    [插图]

    代码运行后,当光标滑过“标题”链接后,相应的“内容”将被显示,如图4-6所示。当光标滑出“标题”链接后,相应的“内容”则被隐藏,如图4-7所示。

    [插图]

    图4-6 内容显示

    [插图]

    图4-7 内容隐藏

    在上面几个例子中,分别用bind()方法给“标题”绑定了click事件、mouseover事件和mouseout事件,绑定方法都一样。除此之外,bind()方法还能绑定其他所有的JavaScript事件。

    4.简写绑定事件

    像click、mouseover和mouseout这类事件,在程序中经常会使用到,jQuery为此也提供了一套简写的方法。简写方法和bind()方法的使用类似,实现的效果也相同,惟一的区别是能够减少代码量。

    例如把上面的例子改写成使用简写绑定事件的方式,代码如下:

    [插图]

    4.1.3 合成事件

    jQuery有两个合成事件—hover()方法和toggle()方法,类似前面讲过的ready()方法,hover()方法和toggle()方法都属于jQuery自定义的方法。

    1.hover()方法

    hover()方法的语法结构为:

    [插图]

    hover()方法用于模拟光标悬停事件。当光标移动到元素上时,会触发指定的第1个函数(enter);当光标移出这个元素时,会触发指定的第2个函数(leave)。

    将上面的例子改写成使用hover()方法,jQuery代码如下:

    [插图]

    代码运行后的效果与下面代码运行后的效果是一样的。当光标滑过“标题”链接时,相应的“内容”将被显示;当光标滑出“标题”链接后,相应的“内容”则被隐藏。

    [插图]

    注意:(1)CSS中有伪类选择符,例如“:hover”,当用户光标悬停在元素上时,会改变元素的外观。在大多数符合规范的浏览器中,伪类选择符可以用于任何元素。然而在IE 6浏览器中,伪类选择符仅可用于超链接元素。对于其他元素,可以使用jQuery的hover()方法。(2)hover()方法准确来说是替代jQuery中的bind ("mouseenter")和bind ("mouseleave"),而不是替代bind ("mouseover")和bind ("mouseout")。因此当需要触发hover()方法的第2个函数时,需要用trigger ("mouseleave") 来触发,而不是trigger ("mouseout")。

    2.toggle()方法

    toggle()方法的语法结构为:

    [插图]

    toggle()方法用于模拟鼠标连续单击事件。第1次单击元素,触发指定的第1个函数(fn1);当再次单击同一元素时,则触发指定的第2个函数(fn2);如果有更多函数,则依次触发,直到最后一个。随后的每次单击都重复对这几个函数的轮番调用。

    在前面的加强效果的例子中,使用了以下jQuery代码:

    [插图]

    虽然上面的代码能实现需要的效果,但是选择的方法并不是最适合的。如果需要连续单击“标题”链接,来达到使“内容”隐藏和显示的目的,那么很适合使用toggle()方法。原理如下:

    [插图]

    使用toggle()方法来改写上面的例子,jQuery代码如下:

    [插图]

    通过使用toggle()方法不仅实现了同样的效果,同时也简化了代码。

    toggle()方法在jQuery中还有另外一个作用:切换元素的可见状态。如果元素是可见的,单击切换后则为隐藏;如果元素是隐藏的,单击切换后则为可见的。因此上面的代码还可以写成如下jQuery代码:

    [插图]

    3.再次加强效果

    为了能有更好的用户体验,现在需要在用户单击“标题”链接后,不仅显示“内容”,而且高亮显示“标题”。为了完成这一功能,首先在CSS中定义一个高亮的样式,CSS代码如下:

    [插图]

    接下来需要完成以下几个步骤。
    (1)等待DOM装载完毕。
    (2)找到“标题”元素,添加toggle()方法,在toggle()方法里定义两个函数,分别代表显示和隐藏。
    (3)在显示函数里,给“标题”添加高亮class。
    (4)在隐藏函数里,移除“标题”的高亮class。

    然后编写如下jQuery代码:

    [插图]

    运行代码后,如果“内容”是显示的,“标题”则会高亮显示;如果“内容”是隐藏的,则不会高亮显示“新闻标题”,显示如图4-8和图4-9所示效果。

    [插图]

    图4-8 显示时,高亮状态

    [插图]

    图4-9 隐藏时,非高亮状态

    4.1.4 事件冒泡

    1.什么是冒泡

    在页面上可以有多个事件,也可以多个元素响应同一个事件。假设网页上有两个元素,其中一个元素嵌套在另一个元素里,并且都被绑定了click事件,同时<body>元素上也绑定了click事件。完整代码如下:

    [插图]

    页面初始化效果如图4-10所示。

    [插图]

    图4-10 初始化效果

    当单击内部<span>元素,即触发<span>元素的click事件时,会输出3条记录,如图4-11所示。这就是由事件冒泡引起的。

    [插图]

    图4-11 单击内部元素

    在单击<span>元素的同时,也单击了包含<span>元素的元素<div>和包含<div>元素的元素<body>,并且每一个元素都会按照特定的顺序响应click事件。
    元素的click事件会按照以下顺序“冒泡”。
    (1)<span>
    (2)<div>
    (3)<body>

    之所以称为冒泡,是因为事件会按照 DOM的层次结构像水泡一样不断向上直至顶端,如图4-12所示。

    [插图]

    图4-12 冒泡过程

    2.事件冒泡引发的问题

    事件冒泡可能会引起预料之外的效果。上例中,本来只想触发<span>元素的click事件,然而<div>元素和<body>元素的click 事件也同时被触发了。因此,有必要对事件的作用范围进行限制。当单击<span>元素时,只触发<span>元素的click事件,而不触发<div>元素和<body>元素的click事件;当单击<div>元素时,只触发<div>元素的click事件,而不触发<body>元素的click事件。为了解决这些问题,介绍以下内容。

    • 事件对象
      由于IE-DOM和标准DOM实现事件对象的方法各不相同,导致在不同浏览器中获取事件对象变得比较困难。针对这个问题,jQuery进行了必要的扩展和封装,从而使得在任何浏览器中都能很轻松地获取事件对象以及事件对象的一些属性。

    在程序中使用事件对象非常简单,只需要为函数添加一个参数,jQuery代码如下:

    [插图]

    这样,当单击“element”元素时,事件对象就被创建了。这个事件对象只有事件处理函数才能访问到。事件处理函数执行完毕后,事件对象就被销毁。

    • 停止事件冒泡

    停止事件冒泡可以阻止事件中其他对象的事件处理函数被执行。在 jQuery 中提供了stopPropagation()方法来停止事件冒泡。

    jQuery代码如下:

    [插图]

    当单击<span>元素时,只会触发<span>元素上的click 事件,而不会触发<div>元素和<body>元素的click事件。

    可以用同样的方法解决<div>元素上的冒泡问题。

    jQuery代码如下:

    [插图]

    这样,当单击<span>元素或者<div>元素时,就只会输出相应的内容,而不会输出其他的内容,效果如图4-13所示。

    [插图]

    图4-13 单击span元素时
    • 阻止默认行为

    网页中的元素有自己默认的行为,例如,单击超链接后会跳转、单击“提交”按钮后表单会提交,有时需要阻止元素的默认行为。

    在jQuery中,提供了preventDefault()方法来阻止元素的默认行为。

    举一个例子,在项目中,经常需要验证表单,在单击“提交”按钮时,验证表单内容,例如某元素是否是必填字段,某元素长度是否够 6 位等,当表单不符合提交条件时,要阻止表单的提交(默认行为)。

    代码如下:

    [插图]

    当用户名为空时,单击“提交”按钮,会出现图4-14所示的提示,并且表单不能提交。只有在用户名里输入内容后,才能提交表单。可见,prevent Default()方法能阻止表单的提交行为。

    [插图]

    图4-14 表单不会提交

    如果想同时对事件对象停止冒泡和默认行为,可以在事件处理函数中返回false。这是对在事件对象上同时调用stopPrapagation()方法和preventDefault()方法的一种简写方式。

    在表单的例子中,可以把

    [插图]

    改写为:

    [插图]

    也可以把事件冒泡例子中的

    [插图]

    改写为:

    [插图]

    • 事件捕获

    事件捕获和事件冒泡是刚好相反的两个过程,事件捕获是从最顶端往下开始触发。

    还是冒泡事件的例子,其中元素的click事件会按照以下顺序捕获。
    (1)<body>
    (2)<div>
    (3)<span>

    很显然,事件捕获是从最外层元素开始,然后再到最里层元素。因此绑定的click事件,首先会传递给<body>元素,然后传递给<div>元素,最后才传递给<span>元素。

    [插图]

    图4-15 事件捕获过程

    遗憾的是,并非所有主流浏览器都支持事件捕获,并且这个缺陷无法通过JavaScript 来修复。jQuery 不支持事件捕获,如果读者需要使用事件捕获,请直接使用原生的JavaScript。

    4.1.5 事件对象的属性

    jQuery在遵循W3C规范的情况下,对事件对象的常用属性进行了封装,使得事件处理在各大浏览器下都可以正常运行而不需要进行浏览器类型判断。

    (1)event.type

    该方法的作用是可以获取到事件的类型。

    [插图]

    以上代码运行后会输出:

    [插图]

    (2)event.preventDefault()方法

    在本章第4.1.4 小节事件冒泡中已经介绍过该方法,该方法的作用是阻止默认的事件行为。JavaScript中符合W3C规范的preventDefault()方法在IE浏览器中却无效。jQuery对其进行了封装,使之能兼容各种浏览器。

    (3)event.stopPropagation()方法

    在本章第4.1.4小节事件冒泡中已经介绍过该方法,该方法的作用是阻止事件的冒泡。JavaScript中符合W3C规范的stopPropagation()方法在IE浏览器中却无效。jQuery对其进行了封装,使之能兼容各种浏览器。

    (4)event.target

    event.target的作用是获取到触发事件的元素。jQuery 对其封装后,避免了各个浏览器不同标准的差异。

    [插图]

    以上代码运行后会输出:

    [插图]

    (5)event.relatedTarget

    在标准DOM中,mouseover和mouseout所发生的元素可以通过event.target来访问,相关元素是通过 event.relatedTarget 来访问的。event.relatedTarget 在mouseover 中相当于 IE 浏览器的event.fromElement,在mouseout中相当于IE浏览器的event.toElement,jQuery对其进行了封装,使之能兼容各种浏览器。

    (6)event.pageX和event.pageY

    该方法的作用是获取到光标相对于页面的x坐标和y坐标。如果没有使用jQuery时,那么IE浏览器中是用event.x / event.y,而在Firefox浏览器中是用event.pageX /event.pageY。如果页面上有滚动条,则还要加上滚动条的宽度或高度。

    [插图]

    (7)event.which

    该方法的作用是在鼠标单击事件中获取到鼠标的左、中、右键;在键盘事件中获取键盘的按键。比如,获取鼠标的左、中、右键:

    [插图]

    以上代码加载到页面后,用鼠标单击页面时,单击左、中、右键分别返回1、2、3。

    比如,获取键盘的按键:

    [插图]

    (8)event.metaKey

    针对不同浏览器对键盘中的<ctrl>按键解释不同,jQuery也进行了封装,并规定event.metaKey为键盘事件中获取<ctrl>按键。

    注意:更多的event的属性和方法可以访问:http://docs.jquery.com/Events/jQuery.Event

    4.1.6 移除事件

    在绑定事件的过程中,不仅可以为同一个元素绑定多个事件,也可以为多个元素绑定同一个事件。假设网页上有一个<button>元素,使用以下代码为该元素绑定多个相同的事件。

    [插图]

    当单击按钮后,会出现图4-16所示的效果。

    [插图]

    图4-16 绑定3个处理函数

    1.移除按钮元素上以前注册的事件

    首先在网页上添加一个移除事件的按钮。

    [插图]

    然后为按钮绑定一个事件,jQuery代码如下:

    [插图]

    最后需要为该事件编写处理函数用于删除元素的所有click事件,jQuery代码如下:

    [插图]

    因为元素绑定的都是click事件,所以不写参数也可以达到同样的目的,jQuery代码如下:

    [插图]

    下面来看看unbind()方法的语法结构:

    [插图]

    第1个参数是事件类型,第2个参数是将要移除的函数,具体说明如下。
    (1)如果没有参数,则删除所有绑定的事件。
    (2)如果提供了事件类型作为参数,则只删除该类型的绑定事件。
    (3)如果把在绑定时传递的处理函数作为第2个参数,则只有这个特定的事件处理函数会被删除。

    2.移除

    首先需要为这些匿名处理函数指定一个变量。

    例如下面的jQuery代码:

    [插图]

    然后就可以单独删除某一个事件了,jQuery代码如下:

    [插图]

    当单击“删除第二个事件”按钮后,再次单击“点击我”按钮,显示图4-17所示的效果。

    [插图]

    图4-17 第2个函数已经被删除

    另外,对于只需要触发一次,随后就要立即解除绑定的情况, jQuery 提供了一种简写方法——one()方法。One()方法可以为元素绑定处理函数。当处理函数触发一次后,立即被删除。即在每个对象上,事件处理函数只会被执行一次。

    One()方法的结构与bind()方法类似,使用方法也与bind()方法相同,其语法结构如下:

    [插图]

    示例代码如下:

    [插图]

    使用one()方法为<button>元素绑定单击事件后,只在用户第1次单击按钮时,处理函数才执行,之后的单击毫无作用。

    注意:jQuery 1.7版本中新增了on(),off(),delegate()和undelegate()事件绑定。具体介绍可以参考第十章。

    4.1.7 模拟操作

    1.常用模拟

    以上的例子都是用户必须通过单击按钮,才能触发click事件,但是有时,需要通过模拟用户操作,来达到单击的效果。例如在用户进入页面后,就触发click事件,而不需要用户去主动单击。

    在jQuery中,可以使用trigger()方法完成模拟操作。例如可以使用下面的代码来触发id为btn的按钮的click事件。

    [插图]

    这样,当页面装载完毕后,就会立刻输出想要的效果,如图4-18所示。

    [插图]

    图4-18 模拟操作

    也可以直接用简化写法click(),来达到同样的效果:

    [插图]

    2.触发自定义事件

    trigger()方法不仅能触发浏览器支持的具有相同名称的事件,也可以触发自定义名称的事件。

    例如为元素绑定一个“myClick”的事件,jQuery代码如下:

    [插图]

    想要触发这个事件,可以使用以下代码来实现:

    [插图]

    实现效果如图4-19所示。

    [插图]

    图4-19 触发自定义事件

    3.传递数据

    trigger(type,[data])方法有两个参数,第1个参数是要触发的事件类型,第2个参数是要传递给事件处理函数的附加数据,以数组形式传递。通常可以通过传递一个参数给回调函数来区别这次事件是代码触发的还是用户触发的。

    下面是一个传递数据的例子。

    [插图]

    [插图]

    图4-20 传递数据

    4.执行默认操作

    trigger()方法触发事件后,会执行浏览器默认操作。例如:

    [插图]

    以上代码不仅会触发为<input>元素绑定的focus事件,也会使<input>元素本身得到焦点(这是浏览器的默认操作)。

    如果只想触发绑定的focus事件,而不想执行浏览器默认操作,可以使用jQuery中另一个类似的方法——triggerHandler()方法。

    [插图]

    该方法会触发<input>元素上绑定的特定事件,同时取消浏览器对此事件的默认操作,即文本框只触发绑定的focus事件,不会得到焦点。

    4.1.8 其他用法

    前面已经对bind()方法进行了介绍,bind()方法不仅能为元素绑定浏览器支持的具有相同名称的事件,也可以绑定自定义事件。不仅如此,bind()方法还能做很多的事情。

    1.绑定多个事件类型

    例如可以为元素一次性绑定多个事件类型。jQuery代码如下:

    [插图]

    当光标滑入<div>元素时,该元素的class切换为“over”;当光标滑出<div>元素时,class切换为先前的值。这段代码等同于下面的代码:

    [插图]

    很显然,第1种方式能减少代码量,这就是jQuery提倡的“write less,do more”(写得更少,做得更多)理念。

    2.添加事件命名空间,便于管理

    例如可以把为元素绑定的多个事件类型用命名空间规范起来,jQuery代码如下:

    [插图]

    在所绑定的事件类型后面添加命名空间,这样在删除事件时只需要指定命名空间即可。单击<button>元素后,“plugin”的命名空间被删除,而不在“plugin”的命名空间的“dblclick”事件依然存在。

    删除多个事件代码也可以写为以下链式代码,但显然上面的方式写得更少。

    [插图]

    3.相同事件名称,不同命名空间执行方法

    例如可以为元素绑定相同的事件类型,然后以命名空间的不同按需调用,jQuery代码如下:

    [插图]

    当单击<div>元素后,会同时触发click事件和click.plugin事件。如果只是单击<button>元素,则只触发 click 事件,而不触发 click.plugin 事件。注意,trigger(“click!”)后面的感叹号的作用是匹配所有不包含在命名空间中的click方法。

    如果需要两者都被触发,改为如下代码即可:

    [插图]

    到此,jQuery中的事件已经介绍完了。下面将介绍jQuery中的动画。

    3.4小结

    本章开篇简要地介绍了什么是DOM,然后介绍了DOM操作分为DOM Core操作、HTML-DOM操作和CSS-DOM操作,以及它们的功能和用法,然后详细地介绍了jQuery中的DOM操作,例如创建节点,插入节点和设置属性等,最后以一个超链接文字提示和图片提示作为案例,来加深对DOM操作的理解。

    3.3 案例研究—某网站的超链接和图片提示效果

    在这一节中,将以某网站的超链接和图片提示效果为例,来理解和巩固jQuery中的DOM操作。

    1.超链接提示效果

    在现代的浏览器中,它们已经自带了超链接提示,只需在超链接中加入 title 属性就可以了。HTML代码如下:

    [插图]

    然而这个提示效果的响应速度是非常缓慢的,考虑到良好的人机交互,需要的是当鼠标移动到超链接的那一瞬间就出现提示。这时就需要移除<a>标签中的title提示效果,自己动手做一个类似功能的提示。

    [插图]

    图3-37 超链接提示效果

    首先在空白的页面上,添加两个普通超链接和两个带有class的超链接。

    HTML代码如下:

    [插图]

    然后为class为tooltip的超链接添加mouseover和mouseout事件,jQuery代码如下:

    [插图]

    实现这个效果的具体思路如下。
    (1)当鼠标滑入超链接。
    ① 创建一个<div>元素,<div>元素的内容为title属性的值。
    ② 将创建的元素追加到文档中。
    ③ 为它设置x坐标和y坐标,使它显示在鼠标位置的旁边。

    (2)当鼠标滑出超链接时,移除<div>元素。
    根据分析的思路,写出如下jQuery代码:

    [插图]

    运行效果,如图3-38所示。

    此时的效果有两个问题:首先是当鼠标滑过后,<a>标签中的title属性的提示也会出现;其次是设置x坐标和y坐标的问题,由于自制的提示与鼠标的距离太近,有时候会引起无法提示的问题(鼠标焦点变化引起mouseout事件)。

    [插图]

    图3-38 超链接提示

    为了移除<a>标签中自带的title提示功能,需要进行以下几个步骤。

    (1)当鼠标滑入时,给对象添加一个新属性,并把title的值传给这个属性,然后清空属性title的值。
    jQuery代码如下:

    [插图]

    (2)当鼠标滑出时,再把对象的myTitle属性的值又赋给属性title。
    jQuery代码如下:

    [插图]

    注意:为什么当鼠标滑出时,要把属性值又赋给属性title呢?因为当鼠标滑出时,需要考虑再次滑入时的属性title值,如果不将myTitle的值重新赋给title属性,当再次滑入时,title的值就为空了。

    为了解决第2个问题(自制的提示与鼠标的距离太近,有时候会引起无法提示的问题),需要重新设置提示元素的top和left的值,代码如下所示,为top增加了10px,为left增加了20px。

    [插图]

    解决这两个问题后,完整的代码如下:

    [插图]

    此时,鼠标滑入和滑出显示已经没问题了,但当鼠标在超链接上移动时,提示效果并不会跟着鼠标移动。如果需要提示效果跟随鼠标一起移动,可以为超链接加上一个mousemove事件,jQuery代码如下:

    [插图]

    图3-39 提示效果

    [插图]

    这样,当鼠标在超链接上移动时,提示效果也会跟着一起移动了。

    到此,超链接提示效果就完成了,完整的jQuery代码如下:

    [插图]

    2.图片提示效果

    稍微修改上面的代码,就可以做出一个图片的提示效果。

    首先在空白网页中加入图片,HTML代码如下:

    [插图]

    设置样式后,初始化效果如图3-40所示。

    [插图]

    图3-40 初始化效果

    参考前面的超链接提示效果的代码,只需要将创建的<div>元素的代码由

    [插图]

    改为

    [插图]

    就可以了。当鼠标滑过图片后,显示效果如图3-41所示。

    [插图]

    图3-41 图片提示效果

    为了使效果更为人性化,还需要为图片增加说明文字,即提示出来的大图片下面出现图片相应的介绍文字。

    可以根据超链接的title属性值来获得图片相应的介绍文字,jQuery代码如下:

    [插图]

    然后将它追加到<div>元素中,代码如下:

    [插图]

    注意:在判断this.myTitle是否为" "时,使用了三元运算。三元运算结构为:Boolean?值1 : 值2。它的第1个参数必须为布尔值。当然三元运算也可以用“if(){ }else{ }”代替,例如: [插图]

    这样,图片提示效果就完成了,当鼠标滑过图片时,图片会出现预览的大图,大图下面还会有介绍文字。效果如图3-42所示。

    [插图]

    图3-42 图片提示效果

    完整的jQuery代码如下:

    [插图]

    到此,超链接提示和图片提示效果就都完成了。此处仅仅用了 jQuery 中的几个DOM 操作方法,就完成了很友好的动态提示效果。