jQueryUI-1-10-jQuery-的用户界面库-全-

jQueryUI 1.10:jQuery 的用户界面库(全)

原文:zh.annas-archive.org/md5/67D4BB507B37025C38972681032F3C25

译者:飞龙

协议:CC BY-NC-SA 4.0

序言

现代 Web 应用程序用户界面设计需要快速开发和经过验证的结果。jQuery UI 是 jQuery JavaScript 库的官方插件套件,为您提供了一个坚实的平台,您可以在此平台上最大程度地兼容性、稳定性和最少时间和精力的情况下构建丰富而引人入胜的界面。

jQuery UI 拥有一系列现成的、外观精美的用户界面小部件和一套全面的核心交互助手,设计成以一种一致且开发者友好的方式进行实现。有了所有这些,您需要亲自编写的代码量从构思到完成项目的过程中都大大减少了。

特别为 jQuery UI 版本 1.10 重新修订,本书旨在通过分解每个组件并引导您逐步构建知识的示例,最大限度地提高您对库的体验,从而使您从初学者到高级用户的使用经验变得更加简单易行。

在本书中,您将学习如何初始化每个组件的基本默认实现,然后看到如何轻松地定制其外观并配置其行为以使其适应应用程序的要求。您将查看每个组件 API 提供的配置选项和方法,以了解如何使用它们发挥库的最佳功能。

事件在任何现代 Web 应用中都扮演着关键角色,如果要满足预期的最低交互和响应要求的话。每一章都会展示组件触发的自定义事件以及这些事件如何被拦截和处理。

本书涵盖的内容

第一章,介绍 jQuery UI,让您了解库的确切内容、从哪里下载以及其中的文件结构。我们还将研究 ThemeRoller,哪些浏览器支持该库,它的许可证情况以及如何简化 API 以使组件具有一致且易于使用的编程模型。

第二章,CSS 框架和其他实用程序,详细介绍了广泛的 CSS 框架,该框架通过 Themeroller 提供了丰富的集成主题环境,并允许开发人员轻松提供自己的自定义主题或皮肤。我们还涵盖了新的位置实用程序,并查看了它提供的所有独特功能和一系列配置选项。

第三章,使用选项卡小部件,介绍了第一个小部件,即选项卡小部件,这是一种简单但有效的呈现结构化内容的交互式小部件。

第四章, 手风琴组件,着眼于手风琴组件,另一个用于有效展示内容的组件。交互性强,吸引人,手风琴为任何网页增添了不少价值,其 API 完全开放,可以准确展示它的使用方法。

第五章, 对话框,专注于对话框组件。对话框的行为方式与标准的浏览器警报相同,但它以一种更不具侵入性和更友好访问者的方式来完成。我们将看看如何对其进行配置和控制以提供最大的益处和吸引力。

第六章, 滑块和进度条组件,提供了一个不太常用但同样有价值的用户界面工具,用于收集访问者的输入,并向他们展示操作的结果。本章将仔细查看这两个组件的 API,看看它们可以实现的各种方式,并在我们的网络应用中充分利用。

第七章, 日期选择器组件,着眼于日期选择器。该组件将大量功能打包成一个引人入胜且高度可用的工具,让您的访问者轻松选择日期。我们将看到其 API 可能实现的广泛配置范围,以及看到像换肤和本地化这样常见任务是如何容易实现的。

第八章, 按钮和自动完成组件,着眼于全新的按钮和最近重新启用的自动完成。长期使用该库的用户将会记得以前版本的库中的自动完成。该组件现在已经全新回归,根据库的最新版本进行了完全更新,本章中我们将看到它如何能够产生巨大的效果。

第九章, 创建菜单,将向我们展示如何在我们的网站或应用程序中创建并添加菜单。我们将看到,通过最少的代码,我们可以将一堆普通的超链接转变为一个交互式的系统,用于在您的网站中进行导航,这将有助于吸引您网站的访问者,并且轻松找到内容。

第十章, 工作中的工具提示,将向我们展示如何通过最小的努力,轻松提供基于上下文的支持系统,向最终用户显示重要的消息或反馈。在访问者在您的网站上可能无意中输入不正确信息的情况下,这一点尤为重要;我们可以帮助他们重新回到正确的方向!

第十一章, 拖放,开始研究低级交互助手,首先解决相关的拖放组件。我们将看看它们如何分别实现以及如何一起使用来增强您的用户界面。

第十二章, 可调整大小组件,介绍了调整大小组件以及如何与本书中早期看到的对话框小部件一起使用。我们将看到如何将其应用于页面上的任何元素,以便以平滑和吸引人的方式调整其大小。

第十三章, 使用 jQuery UI 进行选择和排序,着眼于本章的最后两个交互帮助程序;可选择和可排序组件。我们可以使用这些组件在网站或应用程序中选择和排序元素,尽管在处理列表时,可排序组件确实发挥了作用,因为您可以通过拖动项目将它们重新排序到列表中的新位置。这两个组件都可以帮助您为您的站点增加高水平的专业性和交互性,同时模糊了桌面应用程序和基于浏览器的应用程序之间的界限。

第十四章, UI 特效,专门介绍了该库中包含的特殊效果。我们将介绍一系列不同的效果,使您能够以多种吸引人和迷人的动画展示、隐藏、移动和摆动元素。

第十五章小部件工厂,本书可下载章节提供了对小部件工厂的全面介绍,以及它如何让我们快速轻松地创建自己的 jQuery UI 插件。小部件工厂为您解决了许多常见问题,并且可以极大地提高生产力;它还大大提高了代码重用性,使其非常适合 jQuery UI 以及许多其他有状态的插件。您可以在www.packtpub.com/sites/default/files/downloads/2209OS_Chapter_15.pdf找到本章。

附录, 帮助和支持,涵盖了下载库的基础知识。它提供了“获取帮助”部分,为读者提供了他们在整本书中的所有问题的答案。

您需要准备什么来阅读本书

您只需要一个简单的文本或代码编辑器和一个浏览器就可以完成本书中大多数示例的工作。一两个更高级的示例依赖于 PHP,但为了方便起见,我已将这些示例包含在本书附带的代码下载中。

这本书是为谁准备的

本书是为需要快速学习如何使用 jQuery UI 的前端开发人员或希望了解 jQuery UI 的功能、行为和外观的设计师准备的。要充分利用本书,您应该对 HTML、CSS 和 JavaScript 有很好的工作知识,并且最好熟练使用 jQuery。

惯例

在本书中,您会发现一些不同种类信息之间的文本样式。以下是这些样式的一些示例,以及它们的含义解释。

文本中的代码字词、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 用户名显示如下:“当提示选择解压缩档案的位置时,请选择我们刚创建的jqueryui文件夹。”

代码块设置如下:

<link rel="stylesheet"
href="development-bundle/themes/base/jquery.ui.tabs.css">
<link rel="stylesheet"
href="development-bundle/themes/base/jquery.ui.theme.css">

当我们希望引起您对代码块的特定部分的注意时,相关的行或项将以粗体显示:

$(".ui-positioned-element").position({
 of: ".ui-positioning-element",
 my: "right bottom",
 at: "right bottom"
});

新术语重要单词以粗体显示。例如,您在屏幕上看到的单词,在菜单或对话框中看到的单词,都会以如下形式出现在文本中:“当我们查看页面并选择Images选项卡后,稍等片刻,我们应该看到六张新图片。”

注意

警告或重要说明会以此框的形式出现。

小贴士

小贴士和技巧会以这种方式出现。

第一章:介绍 jQuery UI

欢迎来到jQuery UI 1.10: 用于 jQuery 的用户界面库。这个资源旨在带您从您的第一步到使用 JavaScript UI 小部件和交互助手的高级用法,这些小部件和交互助手是构建在非常流行和易于使用的 jQuery 之上的。

jQuery UI 扩展了基础的 jQuery 库,提供了一套丰富和交互式的小部件以及节省代码的交互助手,旨在增强您的网站和 Web 应用程序的用户界面。jQuery Core 和 UI 都根据严格的编码约定构建,这些约定定期更新,并遵循当前的 JavaScript 设计最佳实践。作为 jQuery 的官方 UI 库,正是对当前 JavaScript 标准的严格遵守使其成为 jQuery 中最好的 UI 库之一。

在本章中,我们将涵盖以下主题:

  • 如何获取库的副本

  • 如何设置开发环境

  • 库的结构

  • 主题生成器

  • 浏览器支持

  • 库的许可形式

  • API 的格式

由于其不断增长的常见 UI 小部件、高度可配置性和出色的实现便利性,jQuery 迅速成为当今最流行的 JavaScript 库之一,被许多知名公司支持和使用,如 Microsoft、WordPress、Adobe 和 Intel。

jQuery UI 运行在 jQuery 之上,因此用于初始化、配置和操作不同组件的语法与 jQuery 具有相同舒适和易用的风格。由于 jQuery 构成了 UI 的基础,我们也可以利用所有出色的 jQuery 功能。该库还受到一系列非常有用的工具的支持,例如提供一系列辅助 CSS 类的 CSS 框架,以及优秀的 ThemeRoller 应用程序,该应用程序允许我们可视化地创建自己的自定义主题,或者从日益增长的预定义主题库中进行选择。我们将在本章稍后查看 ThemeRoller 应用程序。

在本书中,我们将查看构成该库的每个现有组件。我们还将查看它们的配置选项,并尝试它们的方法,以充分理解它们的工作原理和能力。在本书结束时,您将成为 jQuery UI 库中每个小部件配置和使用的专家。当我们添加新的小部件或交互助手时,由于我们实现库中不同组件的一致性,当我们创建自定义组件时,我们将已经具备了基本的工作知识。因此,我们只需要学习任何特定于小部件的功能,以掌握我们希望使用的特定组件。

下载该库

本书专门针对 jQuery UI 的版本 1.10,并且需要 jQuery 1.6 或更高版本;在本书中,我们将在代码示例中使用 jQuery 2.0.3。

注意

如果你仍然需要支持 IE6,那么可以下载遗留的 jQuery UI 库的版本 1.9.2。你还需要使用 jQuery 1.10 的副本,因为 jQuery 2.0 不支持 IE 6-8。

要获取库的副本,我们应该访问 www.jqueryui.com/download 上的下载构建器。该工具为我们提供了一系列不同的选项,用于构建一个符合我们特定需求的下载包。以下截图显示了 下载构建器

下载库

我们可以下载完整的当前版本发布或遗留版本的完整包。我们还可以仅选择我们想要的组件并下载自定义包——这在生产环境中特别推荐,因为我们只使用 UI 库的子集;这有助于减少在查看页面时使用的带宽。

页面布局友好且易于使用。它列出了所有不同组件及其各自的分组(UI 核心交互小部件),并允许我们从 24 种不同的预设计主题(或不使用主题)中进行选择。页面还提供了有关包的信息(包括其压缩和未压缩大小)。

小贴士

如果作为开发人员想要查看 jQuery UI 在源代码控制下的最新快照,那么可以从 GitHub 下载一个副本,该副本可在 github.com/jquery/jquery-ui 上获取。

我们稍后将查看库中找到的不同文件,但现在我们应该下载完整的库。它将包含我们需要的一切,包括 JavaScript 和 CSS 文件,以及依赖于不同组件的当前主题中的任何图像。它甚至包含了 jQuery 的最新版本,因此我们不需要担心单独下载这个。

现在,只需使用页面顶部的自定义 下载 链接,然后在接下来的页面上选择 Smoothness 作为主题,然后点击 下载。我们将在下一章中介绍下载和使用其他主题。

附带本书的代码下载包括每个章节练习文件夹中的 jQuery 2.03 的副本。如果你需要下载新副本,可以这样做——下载新副本的说明在 附录 帮助与支持 中。

使用托管版本的 jQuery UI

我们不需要下载库以便在生产 Web 应用程序中实现它。jQuery 和 jQuery UI 都托管在 Google、CDNJS、Microsoft 和 MediaTemple(他们为 jQuery UI 提供 CDN)提供的内容交付网络(CDN)上。

在接收大量国际流量的实时站点上,使用 CDN 将有助于确保库文件从距离访问者较近的服务器下载到他们的计算机上。这有助于加快响应速度,并节省我们自己的带宽。但这不推荐用于本地开发!

提示

托管的文件

如果你想要使用 CDN 链接,那么可以在以下位置找到:

设置开发环境

我们需要一个位置来解压 jQuery UI 库,以便在我们自己的文件中轻松访问它的不同部分。我们应该首先创建一个project文件夹,将所有示例文件以及整个库和其他相关资源保存在其中。

在你的C:驱动器或你的主目录中创建一个名为jqueryui的新文件夹。这将是我们项目的根文件夹,也将是我们在书中制作的所有示例文件的存储位置。

注意

这本书附带的代码下载的结构将反映我们正在创建的本地环境。

要解压这个库,你可以使用 Windows Explorer(如果在 PC 上工作),或者像 7-zip 这样的压缩程序。当解压这个库时,请选择我们刚刚创建的jqueryui文件夹。如果你是 Mac 用户,你可能需要将jqueryui-1.10.3.custom文件夹中的内容复制到我们刚刚创建的新jqueryui文件夹中。(我们将在本章的后面介绍jqueryui文件夹的结构。)

注意

7-zip 是一个类似于 WinZip 或 WinRAR 的开源存档应用程序;我个人觉得它更好、更容易使用。你可以免费从www.7-zip.org下载它。

我们将要查看的代码示例使用其他资源,主要是图像,但偶尔也会使用一些 PHP 文件。在Packt Publishing网站上提供的附带代码下载包含我们将使用的所有图像。如果可以的话,你应该从www.packtpub.com/support/book/user-interface-library-for-jquery下载这个。你需要在jqueryui项目文件夹内创建一个名为img的新文件夹,然后将存档中图像文件夹内的所有图像解压到这个新文件夹中。

一旦你解压了jqueryui文件夹并添加了任何所需的额外文件夹,你将看到类似于以下屏幕截图的东西——这里我以第五章为例,需要创建一个额外的img文件夹:

建立开发环境

代码下载还包含所有示例以及库本身。提供这些文件是希望它们仅用于参考目的。我建议你在阅读时跟随书中的示例,手动创建每个文件,而不是仅仅参考代码下载中的文件。学习编码的最佳方式就是编写代码。

这就是我们需要做的一切,不需要安装任何额外的平台或应用程序,也不需要配置或设置任何内容。只要您有一个浏览器和某种代码或文本编辑器,一切都已准备好开始使用该库进行开发。

有很多可用的编辑器,其中任何一个都可以与 jQuery UI 一起使用,如果您还没有首选的编辑器,那么对于 Windows 用户,您可以尝试 Notepad++(可以从www.notepad-plus-plus.org免费下载),或 Sublime Text 2(共享软件,可以从www.sublimetext.com/2下载)。我建议避免使用占用内存过多的集成开发环境,因为它们倾向于过多地促使工作,从而影响使用 jQuery UI 时的学习曲线。

注意

对于那些喜欢使用本地 Web 服务器进行开发的人来说,您可以使用像 WAMP(对于 PC)或 MAMP(对于 Mac)这样的东西,如果您还没有将其设置为日常工作流程的一部分。Linux 用户应该找到适合的 Web 服务器,可以从他们的发行版中找到。

理解库的结构

让我们花点时间来查看一下库解压后的结构,这样我们就知道在哪里查找特定的工具和文件。这将让我们对其构成和结构有所了解。打开我们解压库的地方的jqueryui文件夹。此文件夹的内容应该如下:

  • 一个css文件夹

  • 一个development-bundle文件夹

  • 一个js文件夹

  • 一个index.html文件

我们可以从以下截图中看到结构是什么样的:

理解库的结构

为了使用 jQuery UI,只需知道jscss文件夹就足够了;这些可以像现在这样直接放入您的站点结构中,并从您的代码中相应地引用相关的压缩文件。

如果您是以开发者身份使用该库,则我建议使用development-bundle文件夹;其中包含与各个源文件相同的代码,但以未压缩的格式提供。

详细检查文件夹结构

对于大多数人来说,了解 jQuery UI 库的构成并不必要;毕竟,可以将两个关键文件夹简单地放入您的站点中,并相应地引用它们。在这种情况下,您可能希望跳过本节,转到使用 ThemeRoller

如果您的技能更加先进,并且您想更多地了解库的结构,请继续阅读。我建议您在阅读本节时下载 jQuery 的副本,以便更好地理解库的组成。

css 文件夹用于存储与库一起提供的完整 CSS 框架。在此文件夹中,将有一个具有我们在构建下载包时选择的主题名称的目录。其中包含一个包含所有 CSS 框架的单个文件,以及一个包含主题使用的所有图像的文件夹。我们还可以将我们将在此 css 目录中创建的 css 文件存储在其中。

js 文件夹包含经过缩小的 jQuery 版本和完整的 jQuery UI 库,其中所有组件都打包到一个文件中。在实际项目中,我们会将 jscss 文件夹放入我们的网站。

索引是一个 HTML 文件,简要介绍了库,并显示了所有小部件以及一些 CSS 类。如果这是您第一次使用该库,您可以查看此文件,以查看我们将在本书中使用的一些内容。

development-bundle 目录包含一系列资源,以帮助我们使用库进行开发。它包括以下子目录:

  1. 一个 demos 文件夹

  2. 一个 docs 文件夹

  3. 一个 external 文件夹

  4. 一个 themes 文件夹

  5. 一个 ui 文件夹

以下截图显示了文件夹结构的外观:

详细检查文件夹结构

目录中还包含许可文件、JSON 源文件、显示库版本及其主要贡献者的文档,以及一个未压缩版本的 jQuery。

demos 文件夹包含一系列基本示例,展示所有不同组件的功能。docs 文件夹包含每个不同组件的 API 文档。

external 文件夹包含一组对开发人员可能有用的工具。它们如下:

  • globalize 插件

  • jshint 插件

  • mousewheel 插件

  • 单元测试套件 qunit(包括一个 JavaScript 文件和一个 CSS 文件)

globalize 插件为 jQuery 提供本地化支持,并可用于在超过 350 种文化中格式化字符串、日期和数字。jshint 插件是 jslint 插件的一个衍生工具,用于检测 JavaScript 代码中的错误和潜在问题,并强制执行您自己的编码约定。由 Brandon Aaron 设计的 mousewheel 插件为您的网站或在线应用程序添加了跨浏览器鼠标滚轮支持。QUnit 框架是 jQuery 的单元测试套件,我们可以使用它来运行我们创建的任何代码的单元测试。

提示

要获取有关 QUnit 的更多信息,请访问 docs.jquery.com/QUnit

themes文件夹包含默认主题或在下载构建器过程中选择的主题。稍后下载或创建的其他主题也可以存储在这里。

ui文件夹包含库的各个组件的单独未压缩源文件。

注意

如果您从主页选择稳定下载选项,您会发现内容呈现不同——稳定下载选项只包含development-bundle文件夹的内容,并且默认包含的主题称为Base。这在视觉上类似于我们在自定义包中下载的Smoothness主题。

使用 ThemeRoller

ThemeRoller 是一个使用 jQuery 和 PHP 编写的自定义工具。它允许我们直观地生成自己的 jQuery UI 主题,并将其打包成一个方便下载的存档文件,然后我们可以将其直接放入我们的项目中,无需进行进一步的编码(当然,除了在 HTML <link>元素中使用样式表之外)。

ui.jquery.com/themeroller上托管的 ThemeRoller 是由 Filament Group, Inc.创建的,并使用了一些发布到开源社区的 jQuery 插件。它可用于为 jQuery UI 1.10 或 jQuery UI 1.9 的传统版本生成主题。

提示

托管主题

如果我们使用主站点提供的主题之一,甚至不需要下载主题。在生产环境中,您可能更喜欢使用 CDN 版本的主题,就像您可能使用 CDN 链接来引用主库一样。

您可以使用以下链接导入基本或光滑主题:code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css。如果您想使用其他主题之一,请将 URL 中的光滑替换为您喜欢的主题。

ThemeRoller 肯定是创建自己的 jQuery UI 主题的最全面的工具。我们可以非常快速和轻松地创建一个包含所有所需的样式的完整主题,以便针对组成库的不同小部件进行定位,包括我们将需要的图像。

使用 ThemeRoller

如果您之前看过index.html文件,那么 ThemeRoller 首发页面将会让您立即感到熟悉,因为它显示了页面上所有 UI 小部件,并使用默认的Smoothness主题进行美化。

ThemeRoller 页面左侧有一个交互式菜单,用于操作该应用程序。菜单中的每个项目都会展开,让您访问每个部件的可用样式设置,如小部件的内容可点击区域,小部件的标题内容区域以及其他相关内容,如警告和错误消息。

在这里,我们可以轻松创建自定义主题,并且可以在应用于页面上每个小部件的不同可见部分时立即看到更改,如下图所示:

使用 ThemeRoller

如果在创建主题时感觉不太灵感,还有一个预配置主题的画廊,您可以立即使用它来生成一个完全配置的主题。除了方便之外,这些预选主题最好的一点是,当您选择其中一个时,它会加载到左侧菜单中。因此,您可以根据需要轻松进行小调整。

这是创建与现有站点样式匹配的视觉上吸引人的自定义主题的绝佳方法,也是创建自定义皮肤的推荐方法。

安装和使用新主题就像选择或创建它一样简单。上面截图中的 下载主题 按钮将我们带回下载生成器,该生成器将新主题的 CSS 和图像集成到下载包中。

如果我们只想要新主题,我们可以取消选择实际组件,只下载主题。下载后,在下载的存档中的 css 文件夹中将包含一个以主题名称命名的文件夹。我们只需将此文件夹拖放到我们自己的本地 css 文件夹中,然后从我们的页面链接到样式表。

在本书中我们不会详细介绍这个工具。我们将重点放在需要在我们自己的定制样式表中手动覆盖的样式规则上,以手动生成所需的示例外观。

将组件类别分类

jQuery UI 库中有三种类型的组件,如下所示:

  • 低级交互助手:这些组件主要设计用于鼠标事件

  • 小部件:这些组件在页面上产生可见对象

  • 核心组件:这些组件是库的其他部分所依赖的组件

让我们花点时间考虑构成每个类别的组件,从核心组件开始。

核心组件包括:

  • 核心

  • 小部件

  • 鼠标

  • 定位

核心文件建立了所有组件使用的构造,并添加了一些所有库组件共享的核心功能,例如键盘映射、父级滚动和 z-index 管理器。这个文件不是设计用于独立使用的,并且不暴露任何可以在另一个组件之外使用的功能。

交互助手包括以下组件:

  • 可拖动的

  • 可放置的

  • 可调整大小

  • 可选择的

  • 可排序

交互助手向任何元素添加基本的基于鼠标的行为;这使您可以创建可排序的列表,在飞行中调整元素的大小(例如对话框)或甚至构建功能(例如基于拖放的购物车)。

较高级别的小部件(在撰写时)包括:

  • 折叠菜单

  • 自动完成

  • 按钮

  • 日期选择器

  • 对话框

  • 菜单

  • 进度条

  • 滑块

  • 标签页

  • 菜单

  • 工具提示

小部件是将桌面应用程序功能的丰富性带入 Web 的 UI 控件。每个小部件都可以完全自定义,外观和行为。

介绍小部件工厂和效果

当使用 jQuery UI 的小部件时,你会遇到小部件工厂。它实际上创建了库公开的所有可见小部件的基础。它实现了所有小部件共享的 API,例如 createdestroy 方法,并提供了事件回调逻辑。它还允许我们创建继承共享 API 的自定义 jQuery UI 小部件。我们将在本章后面详细介绍小部件工厂。

除了这些组件和交互式助手之外,还有一系列 UI 效果,可以在页面上的目标元素上产生不同的动画或过渡效果。这些效果非常适合为我们的页面添加风采和风格。我们将在本书的最后一章中查看这些效果,UI Effects

jQuery UI 简化的 API 的好处在于,一旦你学会了使用所有现有的组件(就像这本书会向你展示的那样),你将能够非常快速地掌握任何新组件。未来版本中还计划添加许多新组件,包括将 jQuery Mobile 合并到库中!

浏览器支持

与 jQuery 本身一样,这个版本的 jQuery UI 官方支持当前和上一个版本的浏览器,尽管该库可以在旧版本的主要浏览器上正常工作,包括以下浏览器:IE7+、Firefox 2+、Opera 9+、Safari 3+ 和 Chrome 1+。

提示

对 IE6 和 IE7 的支持

如前所述,jQuery UI 团队在 UI 1.10 中停止了对 IE6 的支持;尽管如此,你仍然可以通过下载遗留的版本 1.9.2 使用 jQuery UI。IE7 的用户可能会注意到,计划也将放弃对该浏览器的支持;在撰写本文时,这一计划目前计划在版本 1.11 中实现,尽管这尚未确认。

小部件是从语义上正确的 HTML 元素中构建的,根据需要由组件生成。因此,我们不会看到创建或使用过多或不必要的元素。

使用本书示例

这个库和标准 JavaScript 一样灵活。我的意思是,通常有多种方法来做同样的事情,或者达到同样的目的。例如,用于不同组件的配置对象中的回调事件通常可以接受函数引用或内联匿名函数,并且可以同样轻松高效地使用它们。

在实践中,建议尽可能保持代码的最小化(无论如何,jQuery 都可以帮助实现这一点)。但为了使示例更易读和理解,我们将尽可能将代码分离为独立的模块。因此,回调函数和配置选项将与调用或使用它们的代码分开定义。

在本书中,我们将把 JavaScript 和 CSS 代码分开存储到不同的文件中;虽然这对开发工作来说有些过分,但对于生产网站来说是可取的。存在外部js文件中的脚本可被浏览器缓存,从而大大提高加载速度;而直接写在<script>标签中的内联脚本则不能被浏览器缓存。

我还想澄清一点,即本书的整个过程的主要目的是学习如何使用组成 jQuery UI 的不同组件。如果某个示例看起来有点复杂,可能是因为这是暴露特定方法或属性功能的最简单方法,而不是我们编码常规实现所会遇到的情况。

我想在这里补充一下,jQuery UI 库目前正在经历快速扩展、bug 修复和开发阶段。对于这个版本,jQuery 团队正在专注于 bug 修复,以帮助使库尽可能稳定。从长远来看,jQuery UI 团队正在专注于重新设计每个小部件的 API,并计划在未来的版本中添加大量新的小部件,并完成与 jQuery Mobile 已计划的合并。

库许可

与 jQuery 一样,jQuery UI 库也是根据 MIT 开源许可发布的。这是一个非常不限制的许可,允许创建者对其制作进行归属,并保留其知识产权,同时不妨碍我们开发者以任何方式在任何类型的网站上使用该库。

MIT 许可明确规定了软件使用者(在本例中是 jQuery UI)可以自由使用、复制、合并、修改、发布、分发、许可和出售。这让我们可以几乎为所欲为地使用库。这个许可所施加的唯一要求是我们必须保持原始的版权和保修声明完整。

这一点很重要。您可以随意使用库。您可以在库的基础上构建应用程序,然后销售这些应用程序或免费提供。您可以将库放入嵌入式系统,例如手机操作系统,并出售它们。但无论做什么,都要保留带有 John Resig 名字的原始文本文件。您还可以在应用程序的帮助文件或文档中逐字复制它。

MIT 许可非常宽松,但因为它本身没有版权,我们可以自由改变它。因此,我们可以要求软件使用者向我们归功,而不是 jQuery 团队,或将代码冒充为我们自己的。

许可证并不限制我们的任何方式,并且与您可能购买并安装在您自己计算机上的软件附带的许可证不同。在大多数情况下,库的许可将不会成为使用它时的考虑因素。但是,插件作者将希望确保其插件以类似的许可发布。

API 介绍

一旦您使用了库中的任何一个组件,您在使用其他任何组件时会立即感到自如,因为每个组件的方法都以完全相同的方式调用。

每个组件的 API 由一系列不同的方法组成。尽管这些在技术上都是方法,但根据它们的特定功能对它们进行分类可能是有用的。

方法类型 描述
插件方法 此方法用于初始化组件,只是组件名称,后跟括号。我将在本书中始终将其称为插件方法或小部件方法。
共享 API 方法 destroy 方法可用于任何组件,以完全禁用正在使用的小部件,并且在大多数情况下将底层 HTML 返回到其原始状态。option 方法由所有组件使用,用于在初始化后获取或设置任何配置选项。enabledisable 方法由大多数库组件使用,用于启用或禁用组件。所有小部件都公开的 widget 方法返回对当前小部件的引用。
专用方法 每个组件都有一个或多个特定于该特定组件的方法,执行特定的功能。

方法通过将我们想要调用的方法作为简单字符串传递给组件的 plugin 方法,在每个不同的组件中始终一致地调用,该方法接受方法接受的任何参数作为方法名称之后的字符串。

例如,要调用手风琴组件的 destroy 方法,我们只需使用以下代码:

$("#someElement").accordion("destroy");

看,多么简单!所有不同组件公开的每个方法都以相同简单的方式调用。

一些方法,如标准 JavaScript 函数,接受触发组件不同行为的参数。例如,如果我们想在标签部件中调用 disable 方法,则会使用以下代码:

$("#someElement").tabs("disable", 1);

disable 方法与标签部件一起使用时,接受一个整数,该整数指的是小部件内单个标签的索引。同样,要再次启用该标签,我们将使用以下代码中显示的 enable 方法:

$("#someElement").tabs("enable", 1);

再次,我们提供了一个参数来修改方法的使用方式。有时,传递给方法的参数在组件之间会有所不同。例如,手风琴部件不会启用或禁用单个手风琴面板,只会启用或禁用整个部件,因此在方法名称之后不需要其他参数。

option 方法略微比其他常见方法复杂,但它也更强大,并且使用起来同样简单。该方法用于在组件初始化后获取或设置任何可配置选项。

要在 getter 模式中使用 option 方法检索选项的当前值,我们可以使用以下代码:

$("#someElement").accordion("option", "navigation");

前面的代码会返回折叠小部件的 navigation 选项的当前值。因此,要触发 getter 模式,我们只需提供要检索的选项名称。

要改用 setter 模式中的 option 方法,我们可以提供选项名称和新值作为参数:

$("#someElement").accordion("option", "navigation", true);

前面的代码会将 navigation 选项的值设置为 true。请注意,也可以通过传递对象字面量来一次性设置多个不同的选项给 option 方法。例如:

$("#someElement").accordion("option", {
  animate: "bounceslide",
  heightStyle: "fill"
});

如您所见,尽管 option 方法为我们提供了使用 getset 配置选项的功能,但其仍保留了其他方法相同易于使用的格式。

事件和回调函数

每个组件的 API 还包含丰富的事件模型,允许我们轻松地对不同的交互做出反应。每个组件都公开其自己一组独特的自定义事件,但无论使用哪个事件,其使用方式都相同。

在 jQuery UI 中,我们有两种处理事件的方式。每个组件都允许我们添加在指定事件触发时执行的回调函数,作为配置选项的值。例如,要使用选项卡小部件的 select 事件,该事件在每次选择选项卡时触发,我们可以使用以下代码:

var options = {
  select: function() {
  ...
  }
};
$("#myTabs").tabs(options);

事件的名称用作 option 名称,匿名函数用作 option 值。我们将在后面的章节中查看与每个组件一起使用的所有单独事件。

通过使用 jQuery 的 on() 方法,另一种处理事件的方式是。要以这种方式使用事件,我们只需指定组件的名称,然后是事件的名称:

$("#someElement").on("tabsselect", function() {
...
});

通常,但并非总是,使用 on() 方法与回调函数一起使用的回调函数在事件触发后执行,而使用配置选项指定的回调函数在事件触发前直接执行。回调函数在触发事件的 DOM 元素的上下文中调用。例如,在具有多个选项卡的选项卡小部件中,select 事件将由实际选择的选项卡触发,而不是整个选项卡小部件。这对我们非常有用,因为它允许我们将事件与特定选项卡关联起来。

一些由 jQuery UI 组件触发的自定义事件是可取消的,如果停止,则可用于阻止某些操作。其中最好的例子(我们将在本书后面介绍)是通过在 beforeClose 事件的回调函数中返回 false 来阻止对话框小部件关闭:

beforeClose: function() {
  if (readyToClose === false) {
    event.preventDefault();
}

如果在此示例中不满足任意条件,则回调函数将返回 false,并且对话框将保持打开状态。这是一个非常出色且强大的功能,可以让我们对每个小部件的行为进行精细控制。

回调函数参数

使用任何小部件的一个重要特性是其接受回调的能力。我们可以使用回调来运行执行特定任务的匿名函数。例如,我们可以在单击手风琴小部件中的特定标题时每次在屏幕上触发一个警报。

我们向不同事件提供作为回调函数的匿名函数时,这些匿名函数会自动传递两个参数:原始的、扩展的或修改后的事件对象,以及包含有关小部件的有用信息的对象。第二个对象中包含的信息在各组件之间有所不同。举个例子,让我们看看在使用手风琴小部件时可以实现的回调:

$("#myAccordion").accordion({
  activate: function (event, ui) {
    if(ui.newHeader.length > 0){
      alert(ui.newHeader.attr("id"));
    } else {
      // closed
    }
  }
});

在这里,我们将参数传递给函数,并使用它们来确定哪个手风琴标题是打开的,然后在屏幕上显示结果。将这些对象传递给我们定义的任何回调函数的原理适用于所有组件;我们将在后续章节中详细介绍这一点。

摘要

jQuery UI 消除了构建引人入胜和有效用户界面的困难。它提供了一系列组件,可以快速且轻松地直接使用,并且只需少量配置即可。每个组件都公开了一套完整的属性和方法,以便与您的页面或应用程序集成,如果需要更复杂的配置,则可以利用这些属性和方法。

每个组件都设计为高效、轻量级和语义正确,同时利用了 JavaScript 的最新面向对象特性,并使用了简洁、经过充分测试的框架。与 jQuery 结合使用时,它为任何网页开发者的工具包提供了强大的补充。

到目前为止,我们已经看到了如何获取库,如何设置系统以利用它,以及库的结构。我们还看过如何为不同的小部件添加或自定义主题,如何简单而一致地公开库的功能,以及不同类别的组件。在本章的过程中,我们涵盖了一些重要的主题,但现在我们可以开始使用 jQuery UI 的组件,进行一些真正的编码,首先来看看 CSS 框架。

第二章:CSS 框架和其他工具

在 1.7 版中添加,jQuery UI 库包含一个更新的 CSS 框架,可用于有效和一致地为库中提供的每个小部件设置主题。该框架由许多辅助类组成,我们可以在自己的代码中使用,即使我们没有使用库组件。

在本章中,我们将涵盖以下主题:

  • 构成框架的文件

  • 如何使用框架提供的类

  • 如何快速轻松地切换主题

  • 覆盖主题

  • 使用位置工具

处理构成框架的文件

依赖于您选择下载的库的版本,库结构中有两个位置存放着构成框架的 CSS 文件。

以下是它们:

  • css: 此文件夹包含完整的 CSS 框架,包括在构建下载包时选择的主题。所有必需的 CSS 已经放置在一个单独的、精简的样式表中,以最小化生产环境中的 HTTP 请求。CSS 文件存储在一个文件夹中,文件夹的名称取决于下载生成器上选择的主题。该框架的此版本将包含下载生成器中选择的所有组件的样式,因此其大小将根据使用的库的多少而变化。

  • themes: 框架的另一个版本存在于 development-bundle 文件夹中,其中您将找到 themes 文件夹。此文件夹中提供了两个主题——基础主题和在下载库时选择的任何主题。基础主题是一个灰色的、中性的主题,与平滑主题在视觉上完全相同。

在每个主题文件夹中,都有构成框架的各个文件。框架的不同组件被分割到各自的文件中:

组件 用途

|

jquery.ui.all.css

在开发中,可以通过使用此文件链接所有主题所需的文件。它包含了 @import 指令,引入了 ui.base.cssui.theme.css 文件。

|

jquery.ui.base.css

此文件被 ui.all.css 使用。它还包含 @import 指令,引入 ui.core.css 文件以及每个小部件 CSS 文件。但是,它不包含控制每个小部件外观的主题样式。

|

jquery.ui.core.css

此文件提供核心框架样式,如清除辅助程序和通用覆盖。

|

jquery.ui.accordion.css
jquery.ui.datepicker.css
jquery.ui.button.css
jquery.ui.autocomplete.css
jquery.ui.dialog.css
jquery.ui.progressbar.css
jquery.ui.resizable.css
jquery.ui.selectable.css
jquery.ui.slider.css
jquery.ui.spinner.css
jquery.ui.tabs.css
jquery.ui.menu.css
jquery.ui.tooltip.css
jquery-ui.css

这些文件是控制每个小部件布局和基本外观的个别源文件。

|

jquery.ui.theme.css

此文件包含库中每个小部件的完整视觉主题和目标的所有视觉元素。

让我们更详细地查看每个文件。

jquery.ui.all.css

jquery.ui.all.css文件使用 CSS 导入,使用@import规则读取两个文件——jquery.ui.base.cssjquery.ui.theme.css文件。这就是文件中存在的所有内容,以及实现完整框架和选定主题所需的所有内容。

从此文件中找到的两个指令中,我们可以看到使小部件功能的框架部分和赋予其视觉外观的主题之间的分隔。

jquery.ui.base.css

jquery.ui.base.css文件还包括仅有的@import规则,并且导入了jquery.ui.core.css文件以及每个单独的小部件 CSS 文件。此时,我应该提到可调整大小的组件有自己的框架文件,以及每个小部件。

jquery.ui.core.css

jquery.ui.core.css文件为所有组件提供通用样式。它包含以下类:

用途
.ui-helper-hidden 这个类通过display: none隐藏元素。
.ui-helper-hidden-accessible 这个类通过裁剪元素来隐藏它们,以便元素仍然完全可访问。元素没有被隐藏或定位到屏幕外。
.ui-helper-reset 这是 jQuery UI 的重置机制(它不使用单独的重置样式表),它中和了浏览器通过通用元素应用的边距、填充和其他常见默认样式。有关重置默认浏览器样式的重要性的介绍,请访问:sixrevisions.com/css/css-tips/css-tip-1-resetting-your-styles-with-css-reset/
.ui-helper-clearfix .ui-helper-clearfix样式应用于容器本身。
.ui-helper-zfix .ui-helper-zfix类提供了应用于<iframe>元素的规则,以解决使用覆盖时的 z-index 问题。
.ui-state-disabled 这个类将禁用元素的光标设置为默认,并使用important指令确保它不会被覆盖。
.ui-icon 这条规则是库用背景图替换元素的文本内容的方法。设置库中的不同图标的背景图像的责任被委托给jquery.ui.theme.css文件。
.ui-widget-overlay 这个类设置了显示对话框和其他模态弹出窗口时应用于页面的叠加的基本样式属性。由于叠加使用了图像,因此该类的一些样式也在主题文件中找到。

核心文件为框架的其余部分奠定了基础。我们还可以将这些类名赋予我们自己的元素,以在使用库时清除浮动或隐藏元素,并且在使用 ThemeRoller 一致主题的情况下构建新的 jQuery UI 插件时使用。

解释各个组件框架文件

库中的每个小部件以及可调整大小的交互助手都有一个控制 CSS 并使小部件正确运行的框架文件。例如,选项卡小部件中的选项卡标题必须向左浮动,以便将它们显示为选项卡。框架文件设置了此规则。当我们在自定义主题中覆盖框架时,这些样式将需要呈现出来。

这些文件很简短,每个组件使用的规则数量尽可能少,以确保其正确运行。通常,文件非常紧凑(通常不超过 15 条样式规则)。Datepicker 源文件是个例外,因为它需要大量规则才能正确运行。

jquery.ui.theme.css

此文件将根据使用 ThemeRoller 选择或创建的主题进行自定义。

它设置了构成每个小部件的不同元素的所有视觉属性(颜色、图像等)。

jquery.ui.theme.css文件中,有许多注释,其中包含在大括号中的描述性标签。这些称为占位符,当主题生成时,ThemeRoller 会自动更新它们之前的 CSS 样式。

这是为完整主题生成的文件,其中包含在使用 ThemeRoller 创建或选择主题时创建的每个小部件的所有可见部分的样式。当在自定义主题中覆盖框架时,主要是这个文件中的规则将被覆盖。

每个小部件都是由一组共同的元素构成的。例如,每个小部件的外部容器都具有名为ui-widget的类,而小部件内的任何内容都将放在名为ui-widget-content的容器中。正是这种一致的布局和分类约定使得该框架如此有效。

提示

下载示例代码

您可以从您在www.packtpub.com的帐户中下载您购买的所有 Packt 书籍的示例代码文件。如果您在其他地方购买了本书,您可以访问www.packtpub.com/supportand注册,直接将文件发送到您的电子邮件中。

这是框架中使用的最大样式表,其中包含太多类,无法在此完整列出(但现在可以打开它并查看)。以下表格列出了不同类别的类:

类别 用途
容器 此类别为小部件、标题和内容容器设置样式属性。
交互状态 这些类设置了任何可点击元素的默认、悬停和活动状态。
交互提示 此类别为元素应用了视觉提示,包括高亮、错误、禁用、主要和次要样式。
状态和图像 这些类设置了在内容和标题容器中显示的图标的图片,以及包括默认状态、悬停状态、活动状态、高亮状态、焦点状态和错误状态在内的可点击元素的图像。
图像定位 主题中使用的所有图标图像都存储在单个精灵文件中,并通过操作精灵文件的背景位置属性来单独显示它们。这个类别设定了所有个别图标的背景位置。
角半径 CSS3 用于为支持的浏览器(如 Firefox 3+,Safari 3+,Chrome 1+,Opera 10+ 和 IE9+)提供圆角。
叠加 在核心 CSS 文件中定义的通用叠加所使用的图像在这里设置,因为它是一个实现了对指定元素的半透明叠加效果的类。

jQuery UI 文档中详细介绍了主题 API:api.jqueryui.com/category/theming/

链接到所需的框架文件

在开发环境中,为了快速主题化所有 jQuery UI 小部件,我们可以使用jquery.ui.all.css链接到所有个别文件:

<link rel="stylesheet"
href="development-bundle/themes/smoothness/jquery.ui.all.css">

例如,要在测试选项卡小部件等组件时单独使用每个文件,我们将使用以下<link>元素:

<link rel="stylesheet"
  href="development-bundle/themes/base/jquery.ui.core.css">
<link rel="stylesheet"
  href="development-bundle/themes/base/jquery.ui.tabs.css">
<link rel="stylesheet"
  href="development-bundle/themes/base/jquery.ui.theme.css">

当单独链接到 CSS 资源时,应按以下顺序将其添加到 HTML 页面中:core.css,小部件的 CSS 文件,以及theme.css文件。

当然,在生产环境中,我们将使用高效的合并文件来最小化对 CSS 文件的 HTTP 请求数量。我们需要链接到合并的jquery-ui-x.x.x.min.css样式表,该文件位于css/themename/目录中,其中 x.x.x 是您下载的 jQuery UI 的版本号:

<link rel="stylesheet"
  href="css/smoothness/jquery-ui-x.x.x.custom.css">

为了更轻松地编码和方便起见,在我们的所有示例中,我们将链接到development-bundle/themes/base/jquery.ui.all.css文件。如果您按照上一章节所示解压了库,那么与cssdevelopment-bundlejs文件夹一起,先前的 CSS 文件路径将是正确的。如果您使用不同的结构,请相应地修改 CSS 文件的路径。

提示

创建本书的示例

在本书中,您会注意到我们提到将文件保存在jqueryui文件夹中;您可能希望为每个章节创建一个子文件夹,以便代码可以与其他章节分开存储。这在本书附带的代码下载中有所体现。

使用框架类

在实现官方 jQuery UI 小部件的同时,我们还可以在部署自定义插件时使用它。

与容器一起工作

推荐使用容器,因为这意味着我们编写的小部件或插件将准备好 ThemeRoller,并且更容易为最终开发人员提供主题和定制。让我们看看用我们自己的元素使用框架有多容易。

在文本编辑器中,创建一个新文件并添加以下代码:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>CSS Framework - Containers</title>
  <link rel="stylesheet"
    href="development-bundle/themes/base/jquery.ui.all.css">
</head>
<body>
  <div class="ui-widget">
    <div class="ui-widget-header ui-corner-top">
      <h2>This is a .ui-widget-header container</h2>
    </div>
    <div class="ui-widget-content ui-corner-bottom">
      <p>This is a .ui-widget-content container</p>
    </div>
  </div>
</body>
</html>

将此页面保存为containers.html,放在我们在第一章创建的jqueryui项目文件夹中,介绍 jQuery UI,当我们解压缩库时。我们正在从库中的基本开发主题中链接到jquery.ui.all.css文件。如果我们要构建更复杂的小部件,我们可能也想链接到jquery.ui.core.css文件。

在创建小部件或插件时,使用此文件非常重要,因为它可以让我们验证我们为容器提供的类名是否会获取适当的样式,并向我们保证它们将准备好供 ThemeRoller 使用。我们需要自己应用的任何样式都将放入单独的样式表中,就像库中的每个小部件都有自己的自定义样式表一样。

在这个例子中,我们只使用了几个元素。我们的外部容器被赋予了类名ui-widget

在外部容器内部,我们有两个其他容器。一个是ui-widget-heading容器,另一个是ui-widget-content容器。我们还为这些元素提供了圆角类的变体:分别是ui-corner-topui-corner-bottom

在标题和内容容器内部,我们只有一些适当的元素,我们可能想要放入其中,比如标题中的<h2>和内容元素中的<p>。这些元素将继承一些规则,来自各自的容器,但不会直接由主题文件进行样式设置。

当我们在浏览器中查看这个基本页面时,我们应该看到我们的两个容器元素从主题文件中获取样式,如下面的屏幕截图所示:

使用容器

使用交互

让我们看看框架类的更多实际操作。在containers.html中,删除带有<body>标签的标记,并添加以下内容:

<body>
 <div class="ui-widget">
 <div class="ui-state-default ui-state-active ui-corner-all">
 <a href="#">I am clickable and selected</a>
 </div>
 <div class="ui-state-default ui-corner-all">
 <a href="#">I am clickable but not selected</a>
 </div>
 </div>
</body>

我们也要修改标题,以便反映我们在代码中正在创建的内容——删除现有的<title>,并替换为以下内容:

<title>CSS Framework - Interaction states</title>

将此文件保存为interactions.html,放在jqueryui项目文件夹中。在这些示例中,我们定义了两个可点击元素,它们由一个容器<div>和一个<a>元素组成。两个容器都被赋予了类名ui-state-defaultui-corner-all,但第一个还被赋予了选定状态ui-state-active

这将使我们的可点击元素呈现如下外观:

使用交互

CSS 框架不提供对:hover CSS 伪类的样式。相反,它使用一个类名应用一组样式,该类名是使用 JavaScript 添加的。在闭合</body>标签之前,添加以下代码以查看其效果:

<script type="text/javascript" src="img/jquery-2.0.3.js"> </script>
<script>
  $(document).ready(function($){
    $(".ui-widget a").hover(function() {
      $(this).parent().addClass("ui-state-hover");
    }, function() {
      $(this).parent().removeClass("ui-state-hover");    
    });
  });
</script>

将此前一个示例文件的变体保存为interactionsHovers.html

注意

jQuery 的版本号将随着库的不断发展而更改;我们在本书中始终使用版本 2.03。如果版本不同,请将其替换为您下载的版本。

我们简单的脚本将ui-state-hover类名称添加到可点击元素上,当鼠标指针移动到上面时,然后当鼠标指针移开时将其移除。当我们在浏览器中运行页面并悬停在第二个可点击元素上时,我们应该看到ui-state-hover样式:

使用交互

添加图标

框架还提供了一系列可用作图标的图像。更改interactionsHovers.html中的 ui-widget 容器的内容,使其如下所示:

<div class="ui-widget">
  <div class="ui-state-default ui-state-active ui-corner-all">
 <span class="ui-icon ui-icon-circle-plus"></span>

    <a href="#">I am clickable and selected</a>
  </div>
  <div class="ui-state-default ui-corner-all">
 <span class="ui-icon ui-icon-circle-plus"></span>

    <a href="#">I am clickable but not selected</a>
  </div>
</div>

将此保存为icons.htmljqueryui目录中。在这个示例中,我们的嵌套<div>元素,其具有ui-iconui-icon-circle-plus类,从精灵文件中获得了正确的图标:

添加图标

注意

如果您还不熟悉精灵是如何工作的,那么值得了解一下这种技术——请参阅nerdwith.me/news/css-sprites-for-beginners/,了解如何创建精灵图像的示例。如果您需要创建精灵图像,那么csssprites.com/的 CSS Sprites 生成器是一个很好的网站。

如您所见,ui-state-active图标与ui-state-default图标(以及ui-state-hover图标)略有不同。在此示例中,我们没有定位图标,因为这将需要创建一个新的样式表。

本示例的重点是查看如何使用框架的类名称自动添加图标,而无需默认添加任何额外的 CSS 样式。

注意

如果我们想要调整定位,我们可以通过添加额外的样式来覆盖.existing .ui-icon类,例如span.ui-icon { float: left; },这将将图标重新定位到每个<span>中文本的左侧。

详细检查图标

现在我们已经看到一些图标的使用,让我们更详细地了解如何使用它们。

图标以精灵图的形式呈现,作为主题的一部分进行下载。在库中的主要css文件夹中,您会发现不止一个主题文件夹。根据您需要下载的数量,每个主题库都包含多个由 jQuery UI 使用的精灵图像,用于生成图标,例如我们在前面示例中看到的那些。

查看包含我们图标的图像精灵,它们将看起来像下面这样:

仔细检查图标

如果我们检查 DOM 检查器(如 Firebug)中的代码,您将发现至少添加了两种样式,例如:

<span class="ui-icon ui-icon-circle-plus"></span>

图标 CSS 的格式通常遵循.ui-icon-{图标类型}-{图标子描述}-{方向};应该注意,如果你在小部件中使用icon选项,例如手风琴,则会添加第三个类。

每个图标元素都被赋予一个基本类.ui-icon,它将图标的尺寸设置为 16 像素的方块,隐藏内部文本,并使用选择的精灵图像设置背景图像。使用的背景精灵图像将取决于其父容器;例如,在ui-state-default容器中的ui-icon元素将根据ui-state-default的图标颜色进行着色。

添加自定义图标

向小部件添加图标不必局限于库中的图标。你可以使用自定义图标。

要做到这一点,我们有两个选项——你可以引用单个文件,或者使用类似的图像精灵;后者更可取,特别是如果你使用多个自定义图标,因为包含它们的精灵在加载后将被缓存。

提示

你可以在 api.jqueryui.com/theming/icons/ 上看到核心 jQuery UI 库中提供的所有图标及其图标类名的完整列表。

为了引用这些图标,你需要添加你自己的自定义样式,覆盖.ui-icon类——这是为了确保 jQuery UI 不会尝试应用取消你自己样式的样式。这样一个自定义类的示例如下所示:

.ui-button .ui-icon.you-own-cusom-class {
    background-image: url(your-path-to-normal-image-file.png);
    width: your-icon-width;
    height: your-icon-height; 
}
.ui-button.ui-state-hover .ui-icon.you-own-cusom-class {
    background-image: url(your-path-to-highlighted-image-file.png);
    width: your-icon-width;
    height: your-icon-height;
}

我们可以将新样式应用到我们选择的小部件中,就像使用 jQuery UI 按钮的示例所示:

       $('selector-to-your-button').button({
         text: false,
         icons: {
           primary: "you-own-cusom-class"   // Custom icon
         }
       });

只要图标格式正确,并且在我们的代码中正确引用,那么我们可以自由地添加任何我们想要的图标;值得在线上搜索选项,因为会有大量可供使用的图标,例如 fortawesome.github.io/Font-Awesome/icons/ 上的 Font Awesome 库,或者可以从 icomoon.io/ 下载的 IcoMoon。

提示

为什么我的图标会出现在新行上?

在某些情况下,你可能会发现你的图标出现在小部件中的文本上方或下方的新行中,就像本章早些时候的图标示例所示。这是由于.ui-icon类中的display: block属性造成的:

为了解决这个问题,你可以使用浮动属性,并将其设置为适当的左、右或中心位置来显示图标。

使用自定义图标 - 一则说明

如果你决定使用自定义图标,那么没有任何东西会阻止你这样做,这将打开大量的可能性!你需要注意的是,使用自定义图标需要使用两个类——base .ui-icon,然后是你自己的自定义类。这是为了确保图标显示正确,并防止 jQuery UI 尝试覆盖你自己的图标。

如果不注意确保图标的尺寸正确,使用自己的图标可能会与框架内的样式冲突;强烈建议您仔细查看提供的现有图标库,因为 jQuery UI 团队可能已经转换了一些可能有用的内容。另外,线上搜索也可能会有帮助;为 jQuery UI 编写了自定义主题,您可能会找到包含您需要的图标的主题。

交互提示

另一组我们可以使用的类是交互提示。我们将看另一个使用这些的例子。在文本编辑器中的新页面中,添加以下代码。这将创建一个表单示例,我们可以在其中看到提示的作用:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>CSS Framework - Interaction cues</title>
  <link rel="stylesheet" href="development-bundle/themes/base/jquery.ui.all.css">
  <link rel="stylesheet" href="css/jquery.ui.form.css">
</head>
<body>
  <div class="ui-widget ui-form">
    <div class="ui-widget-content ui-corner-all">
      <div class="ui-widget-header ui-corner-all">
        <h2>Login Form</h2>
      </div>
      <form action="#" class="ui-helper-clearfix">
        <label>Username</label>
        <div class="ui-state-error ui-corner-all">
          <input type="text">
          <div class="ui-icon ui-icon-alert"></div>           
          <p class="ui-helper-reset ui-state-error-text">Required field</p>
        </div>
      </form>
    </div>
  </div>
</body>
</html>

将此文件保存为cues.html,放在jqueryui文件夹中。这次我们链接到一个自定义文件,jquery.ui.form.css,我们马上就会创建它。

在页面上,我们有外部小部件容器,具有ui-formui-widget类名。ui-form类将用于从jquery.ui.form.css样式表中选取我们的自定义样式。在小部件内部,我们有ui-widget-headerui-widget-content容器。

在内容部分,我们有一个带有一行元素的<form>,一个<label>元素,后面跟着一个<div>元素,其中硬编码了ui-state-errorui-corner-all类名。

在这个<div>元素内部,我们有一个标准的<input>,一个带有ui-iconui-icon-alert类的<div>,以及一个添加了ui-state-error-text类名的<p>元素。因为<form>将有由于我们将在jquery.ui.form.css中添加的样式而浮动的子元素,所以我们可以利用ui-helper-clearfix类来清除浮动,我们将其添加为一个类名。

现在我们应该创建自定义的jquery.ui.form.css样式表。在文本编辑器中的新文件中,添加以下代码:

.ui-form { width: 470px; margin: 0 auto; }
.ui-form .ui-widget-header h2 { margin: 10px 0 10px 20px; }
.ui-form .ui-widget-content { padding: 5px; }
.ui-form label, .ui-form input, .ui-form .ui-state-error,
.ui-form .ui-icon, .ui-form .ui-state-error p { float: left; }
.ui-form label, .ui-state-error p { font-size: 12px; padding: 10px 10px 0 0; }
.ui-form .ui-state-error { padding: 4px; }
.ui-form .ui-state-error p { font-weight: bold; padding-top: 5px; }
.ui-form .ui-state-error .ui-icon { margin:5px 3px 0 4px; }
.ui-helper-clearfix:before, .ui-helper-clearfix:after { margin-top: 10px; } 

在我们的jqueryui项目文件夹中,有一个名为css的文件夹,用于存储框架的单文件生产版本。我们在本书中创建的所有 CSS 文件也将保存在这里以方便使用。将此文件保存为jquery.ui.form.css,放在css文件夹中。

想象我们有更多的表单元素和一个提交按钮。通过将ui-state-error类添加到<div>元素,我们可以使用表单验证的错误类,如果提交不成功,将显示图标和文本。以下截图显示页面应该是什么样子的:

交互提示

快速轻松地切换主题

一旦我们使用基本主题开发了内容,我们可能会决定将主题更改为与我们整体网站主题更好地匹配的主题;幸运的是,CSS 框架使更换主题变得轻松。看看之前的例子,要改变小部件的外观只需选择一个新的主题使用 ThemeRoller(可在www.jqueryui.com/themeroller获得),然后下载新主题。我们可以通过在下载构建器中选择所有组件并单击下载来下载新主题以获取新主题。

在下载的存档中,会有一个以所选主题命名的目录,比如redmond。我们将theme文件夹从存档中拖到development-bundle\themes文件夹中,并从我们的页面链接新的主题文件,使我们的表单呈现出全新的外观,如下面的截图所示:

快速轻松地切换主题

我用来获得这个截图的主题是 redmond。这个主题使用了各种蓝色的色调,要么是作为背景要么是作为普通文本;选定的选项,比如选项卡标题或小部件中选定的项目将以橙色文本或橙色背景显示。在本书的剩余部分中,我们将使用这个主题,或者我们自己创建的主题。

覆盖主题

使用 ThemeRoller 画廊和自定义工具,我们可以生成大量独特的主题。但有时候我们可能需要比使用 ThemeRoller 能够达到的更深层次的定制化;在这种情况下,我们有两个选择。

我们可以要么自己从头创建完整的主题文件,要么创建一个额外的样式表,只覆盖我们需要的jquery.ui.theme.css文件中的规则。后者可能是最简单的方法,并且需要编写的代码更少。

现在我们将看一下主题的这个方面。如果你已经为之前的示例更改了基本主题,请切换回cues.html<head>中的基本主题。将页面保存为cuesOverridden.html,然后创建以下新样式表:

.ui-corner-all { border-radius: 4px; }
.ui-widget-header { font-family: Helvetica; background:   #251e14; border-radius: 4px 4px 0 0; border: 1px solid #362f2d;color: #c7b299; }
.ui-form .ui-widget-header h2 { margin: 0; padding: 5px; font-style: italic; font-weight: normal; }
.ui-form .ui-widget-content { background: #eae2d8; border: 1px solid #362f2d; border-top: 0; width:  500px; padding: 0; }
.ui-widget-content form { padding: 20px; border: 1px solid #f3eadf; border-radius: 0 0 4px 4px; }
.ui-widget-content .ui-state-error-text { color: #9A1B1E; }
.ui-form .ui-state-error { border-radius:  4px 4px 4px 4px; }

将其保存为overrides.css放在css文件夹中。在这个样式表中,我们主要是覆盖了jquery.ui.theme.css文件中的规则。这些是简单的样式,我们只是改变了颜色、背景和边框。通过在cuesOverridden.html的其他样式表下面添加以下代码行来链接到这个样式表:

<link rel="stylesheet" href="css/overrides.css">

我们谦逊的表单现在应该呈现如下截图中所示:

覆盖主题

只要我们的样式表出现在theme文件之后,并且我们的选择器特异性匹配或超过了jquery.ui.theme.css文件中使用的选择器,我们的规则就会优先。对 CSS 选择器权重的长时间讨论超出了本书的范围。但是,简要解释特异性可能是有益的,因为它是覆盖所选主题的关键。CSS 特异性指的是 CSS 选择器的特异性程度——它越具体,权重就越大,随后将覆盖其他选择器应用于其他选择器所针对的元素的规则。例如,考虑以下选择器:

#myContainer .bodyText
.bodyText

第一个选择器比第二个选择器更具体,因为它不仅使用了目标元素的类名,还使用了其父容器的 ID。因此,它将覆盖第二个选择器,无论第二个选择器是否在其之后出现。

注意

如果您想了解更多关于 CSS 特异性的信息,那么互联网上有许多优秀的文章。作为一个开始,您可能想看看 designshack.net/articles/css/what-the-heck-is-css-specificity/,或者 [reference.sitepoint.com/ css/specificity](http://reference.sitepoint.com/ css/specificity)。或者,您可能想完成克里斯·科耶的示例,网址是 css-tricks.com/specifics-on-css-specificity/

在这个示例中,我们完全控制了我们正在修饰的元素。但是,当与库中的任何小部件或由第三方编写的插件一起工作时,可能会自动生成大量标记,我们无法控制(除非修改实际的库文件本身)。

因此,我们可能需要依赖这种方式来覆盖样式。我们只需在文本编辑器中打开jquery.ui.theme.css文件并查看其中使用的选择器即可找到要覆盖的样式。如果未能做到这一点,我们可以使用 Firebug 的 CSS 查看器来查看我们需要覆盖的规则,就像下面的示例一样:

覆盖主题

提示

DOM 探查器

所有现代浏览器都有像 Firebug 这样的 DOM 探查器和 CSS 检查器,可以用来查看 CSS 规则应用的顺序。使用浏览器的 CSS 检查器通常是检查 CSS 顺序的最方便方式。

定位实用工具

定位实用工具是一个强大的独立工具,用于将任何元素相对于窗口、文档、特定元素或鼠标指针定位。它在库组件中是独一无二的,因为它不需要jquery.ui.core.jsjquery.effects.core.js作为依赖项。

它不公开任何独特或自定义的方法(除了position()方法),也不触发任何事件,但它确实提供了一系列配置选项,让我们可以使用它。这些选项在下表中列出:

选项 格式 用于
at 字符串 指定要对齐的定位元素的边缘。格式为,例如,left bottom。
collision 字符串 当定位元素溢出其容器时,将定位元素移动到替代位置。
my 字符串 指定预期与要定位的元素对齐的定位元素的边缘,例如 right top。
of 选择器,jQuery,对象,事件对象 指定相对于定位元素的元素。当提供选择器或 jQuery 对象时,使用第一个匹配的元素。当提供事件对象时,使用 pageX 和 pageY 属性
using 函数 接受一个函数,实际上定位定位元素。该函数接收一个包含新位置的 top 和 left 值的对象。

使用位置实用程序

使用位置实用程序非常简单。让我们看几个例子;在您的文本编辑器中创建以下页面:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Position Utility - position</title>
  <link rel="stylesheet" href="css/position.css">
  <script src="img/jquery-2.0.3.js"></script>
  <script src="img/jquery.ui.position.js"> </script>
  <script>
    $(document).ready(function() {
      (function($) {
        $(".ui-positioned-element").position({
          of: ".ui-positioning-element"
        });
      })(jQuery);
    });
  </script>
</head>
<body>
  <div class="ui-positioning-element">I am being positioned against</div>
  <div class="ui-positioned-element">I am being positioned </div>
</body>
</html>

将此保存为position.html。在这个例子中,我们还使用了一个非常基本的样式表,其中包含以下样式:

.ui-positioning-element { width: 200px; height: 200px; border: 1px solid #000; }
.ui-positioned-element { width: 100px; height: 100px; border: 1px solid #f00; }

将此文件保存在css文件夹中,命名为position.css。我们正在定位的元素以及我们自身的定位元素可以设置为相对、绝对或静态定位,而不会影响定位元素的行为。如果我们要定位的元素使用其 top、left、bottom 或 right 样式属性移动,我们要定位的元素将考虑到这一点,并且仍然可以正常工作。

在页面上,我们只有两个<div>元素:一个是我们要定位的元素,另一个是我们要定位的实际元素。jQuery 本身是一个要求,所以我们在<head>元素中链接到它,并且我们还链接到位置实用程序的源文件。正如我之前提到的,当单独使用位置时,我们不需要链接到jquery.ui.core.js文件。

我们可以使用的最小配置,就像我们在这个例子中所做的那样,就是设置of选项,以指定我们要定位的元素。当我们只设置了这一个选项时,我们要定位的元素会被放置在我们要定位的元素的正中央,如下面的截图所示:

使用位置实用程序

这本身就非常有用,因为元素不仅在水平方向上居中,而且在垂直方向上也是如此。

通过使用myat属性,我们还可以将定位元素的任何边缘放置在我们正在定位的元素的任何边缘上。更改外部函数中的代码,使其显示如下(新/更改的代码以粗体显示):

$(".ui-positioned-element").position({
 of: ".ui-positioning-element",
 my: "right bottom",
 at: "right bottom"
});

以下截图显示了此代码的输出:

使用定位实用程序

my选项指的是正在定位的元素。该选项的值作为字符串的第一部分被提供,它是水平轴,可以设置为左、中或右。第二部分是垂直轴,可以设置为顶部、中部或底部。

at选项指的是正在定位的元素的水平和垂直边缘。它还接受与my配置选项相同格式的字符串。

解释碰撞避免

定位实用程序具有内置的碰撞检测系统,以防止正在定位的元素溢出视口。我们可以使用两种不同的选项来设置检测到碰撞时发生的情况。默认值为flip,这会导致元素翻转并将其对齐到已配置的相反边缘。

例如,如果我们将一个<div>元素的右边缘定位到另一个元素的左边缘,如果它溢出了视口,它将被翻转,使其右边缘与定位元素的右边缘对齐。

position.html中的配置更改为以下内容:

$(".ui-positioned-element").position({
 of: ".ui-positioning-element",
 my: "right",
 at: "left"
});

这将导致以下定位:

解释碰撞避免

碰撞避免的另一种模式是fit,它会尽可能尊重配置的定位,但调整元素的定位,使其保持在视口内。将碰撞选项配置如下:

$(".ui-positioned-element").position({
 collision: "fit",
 of: ".ui-positioning-element",
 my: "right",
 at: "left"
});

将此文件保存为positionFit.html。这次,元素被尽可能地定位到其预期位置:

解释碰撞避免

提示

我们还可以将collision选项的值设置为none,以完全禁用碰撞检测,并允许定位元素溢出视口。

使用函数进行定位

我们可以将using选项设置为一个函数,并手动定位被定位的元素。更改配置,使其显示如下:

$(".ui-positioned-element").position({
  of: ".ui-positioning-element",
 my: "right bottom",
 at: "right bottom",
 using: function(pos) {
 $(this).css({
 backgroundColor: "#fc7676",
 top: pos.top,
 left: pos.left
 });
 }
});

将此更改保存为positionFunction.html。我们将一个匿名函数作为using选项的值提供。此函数作为单个参数传递,该参数是一个包含属性 top 和 left 的对象,这些属性对应于我们正在定位的元素应该具有的值。

如你从这段代码中所见,我们仍然需要手动定位元素,但该函数允许我们对可能需要的元素进行任何预处理。在函数内部,this对象被设置为被定位的元素。

在实际示例中使用定位小部件

到目前为止,我们已经考虑了使用位置小部件的理论;在转向查看小部件工厂之前,让我们花点时间考虑一下如何在实际情况中使用位置小部件。

一个完美的例子是 jQuery UI 的对话框小部件,配置为作为模态对话框运行。在这里,我们可以使用位置小部件将对话框放置在页面上,相对于按钮当前的位置。

要了解如何做,请将以下代码添加到文本编辑器中的新文件中:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Dialog</title>
  <link rel="stylesheet" href="development-bundle/themes/redmond/jquery.ui.all.css">
  <script src="img/jquery-2.0.3.js"></script>
  <script src="img/jquery.ui.core.js"></script>
  <script src="img/jquery.ui.widget.js"></script>
  <script src="img/jquery.ui.position.js"></script>
  <script src="img/jquery.ui.dialog.js"></script>
  <script src="img/jquery.ui.button.js"></script>
  <script></script>
</head>
<body></body>
</html>

我们需要一些标记,因此请在<body>标签之间添加以下代码:

<div id="myDialog" title="This is the title!">
  Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
  Aenean sollicitudin. Sed interdum pulvinar justo. Nam iaculis
  volutpat ligula. Integer vitae felis quis diam laoreet
  ullamcorper. Etiam tincidunt est vitae est.
</div>
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Aenean sollicitudin. Sed interdum pulvinar justo. Nam iaculis
volutpat ligula. Integer vitae felis quis diam laoreet
ullamcorper. Etiam tincidunt est vitae est.
<button id="showdialog">Click me</button>

最后,为了将其整合并使其正常工作,请在关闭</head>标签之前添加以下脚本作为最后一个条目:

$(document).ready(function($){
  $("#showdialog").button();
  $("#myDialog").dialog({ autoOpen: false, modal: true, });
  $("#showdialog").click(function() {
    $("#myDialog").dialog("open");
  });
  $("#showdialog").position({
    my: "left+20 top+100",
    at: "left bottom",
    of: myDialog
  });
});

如果我们在浏览器中预览这个页面,你会发现当点击按钮时,我们无法对背景中的文本进行任何操作:

在实际例子中使用位置小部件

在这里,我们启动了一个 UI 对话框,并将其配置为作为模态对话框运行;autopen已设置为false,以便在显示页面时不显示对话框。然后,我们创建了一个简单的点击处理程序,在按钮点击时显示对话框;然后调用位置小部件,其中我们设置了myat属性,以正确显示对话框相对于按钮的当前位置。

小部件工厂

jQuery UI 库中的另一个工具是小部件工厂,它是在 jQuery UI 1.8 版中引入的,并且此后已经经历了一些重要变化。它将允许轻松创建小部件的功能分割成一个单独且独立的实用程序文件。这就是jquery.ui.widget.js文件,我们可以使用它轻松创建我们自己的 jQuery UI 插件。就像 jQuery 本身提供fn.extend()方法轻松创建插件一样,jQuery UI 也提供了使插件创建更容易的机制,并确保在新插件中保留常见 API 功能。我们将在本书的一个单独章节中更详细地介绍小部件工厂,该章节可以下载。

总结

在本章中,我们看到了 CSS 框架如何一致地为每个库组件设置样式。我们查看了组成它的文件以及它们如何共同工作以提供完整的外观和感觉。我们还看到了 ThemeRoller 应用程序与框架的紧密集成程度,并且很容易使用 ThemeRoller 安装或更改主题。我们还看到了如果需要对无法仅通过 ThemeRoller 获得的小部件进行根本性自定义,我们如何可以覆盖主题文件。

该章节还介绍了如何构建与框架兼容并可以利用框架的自定义小部件或插件,以及确保我们的创建可以使用 ThemeRoller。我们还可以利用框架提供的助手类,例如ui-helper-clearfix类,来快速实现常见的 CSS 解决方案。

我们还研究了位置实用工具,它允许我们将一个元素的任何边与另一个元素的任何边对齐,为我们提供了一个强大而灵活的定位元素的方式,无论是创建还是操作元素。

在接下来的章节中,我们将开始查看库提供的小部件,从标签小部件开始。

第三章:使用标签小部件

现在我们已经正式介绍了 jQuery UI 库、CSS 框架和一些实用工具,我们可以开始查看库中包含的各个组件了。在接下来的七章中,我们将着眼于小部件。这些是一组视觉吸引力强、高度可配置的用户界面小部件。

UI 标签小部件用于在不同元素之间切换可见性,每个元素都包含通过点击其标签标题可以访问的内容。每个内容面板都有自己的标签。标签标题通常显示在小部件顶部,尽管也可以重新定位它们,使它们出现在小部件底部。

标签被结构化成水平排列在一起,而内容部分除了活动面板外都被设置为display: none。点击一个标签将突出显示该标签并显示其关联的内容面板,同时确保所有其他内容面板都被隐藏。一次只能打开一个内容面板。可以配置标签使得没有内容面板打开。

在本章中,我们将查看以下主题:

  • 小部件的默认实现

  • CSS 框架如何定位标签小部件

  • 如何为一组标签应用自定义样式

  • 使用它们的选项配置标签

  • 内容面板变化的内置转换效果

  • 使用它们的方法控制标签

  • 由标签定义的自定义事件

  • AJAX 标签

下面的截图标有 jQuery UI 标签组件的不同元素:

使用标签小部件

实现一个标签小部件

标签基于的底层 HTML 元素的结构相对严格,小部件需要一定数量的元素才能工作。标签必须由一个列表元素(有序或无序)创建,每个列表项必须包含一个<a>元素。每个链接都需要有一个与链接的href属性关联的指定id的元素。我们将在第一个示例后澄清这些元素的确切结构。

在文本编辑器中创建一个新文件,创建以下页面:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Tabs</title>
  <link rel="stylesheet" href="development-bundle/themes/base/jquery.ui.all.css">
  <script src="img/jquery-2.0.3.js"></script>
  <script src="img/jquery.ui.core.js"> </script>
  <script src="img/jquery.ui.widget.js"> </script>
  <script src="img/jquery.ui.tabs.js"> </script>
  <script>
    $(document).ready(function($){
    $("#myTabs").tabs();
 });
  </script>  
</head>
<body>
  <div id="myTabs">
    <ul>
      <li><a href="#a">Tab 1</a></li>
      <li><a href="#b">Tab 2</a></li>
    </ul>
    <div id="a">This is the content panel linked to the first tab, it is shown by default.</div>
    <div id="b">This content is linked to the second tab and will be shown when its tab is clicked.</div>
  </div>
</body>
</html>

将代码保存为jqueryui工作文件夹中的tabs1.html。让我们回顾一下使用了什么。默认标签小部件配置需要以下脚本和 CSS 资源:

  • jquery.ui.all.css

  • jquery-2.0.3.js

  • jquery.ui.core.js

  • jquery.ui.widget.js

  • jquery.ui.tabs.js

标签小部件通常由若干个标准 HTML 元素构成,以特定方式排列:

  • 调用标签方法的外部容器元素

  • 列表元素(<ul><ol>

  • 为每个标签的<li>元素内的<a>元素

  • 每个标签的内容面板元素

注意

这些元素可以硬编码到页面中,动态添加,或者根据需求可以是两者的混合。

外部容器中的列表和锚元素构成可点击的选项卡标题,用于显示与选项卡关联的内容部分。链接的href属性应设置为带#前缀的片段标识符。它应与形成其关联的内容部分的id属性相匹配。

每个选项卡的内容部分是使用<div>元素创建的。id属性是必需的,并且将由对应的<a>元素进行定位。在此示例中,我们已经使用<div>元素作为每个选项卡的内容面板,但只要提供相关配置并且生成的 HTML 有效,就可以使用其他元素。panelTemplatetabTemplate配置选项可用于更改用于构建小部件的元素(有关更多信息,请参见本章后面的配置部分)。

我们在<head>部分的关闭标签之前链接到库中的多个<script>资源。脚本可以使用document.ready()命令在<head>部分加载,或者在样式表和页面元素之后加载。将它们放在最后加载是一种提高页面视觉加载时间的成熟技术,尽管这样做真正带来了多大的性能优势还有待商榷。

连接到 jQuery 后,我们链接到jquery.ui.core.js文件,该文件是所有组件(除了效果组件,它们有自己的核心文件)所需的。然后链接到jquery.ui.widget.js文件。然后链接到组件的源文件,本例中是jquery.ui.tabs.js

在库中引入的三个必需脚本文件之后,我们可以转向自定义的<script>元素,其中包含创建选项卡的代码。我们在 jQuery 的DOMReady语句中封装用于创建选项卡的代码;这样做可确保代码仅在页面元素加载并准备好进行操作时才执行。我们还通过 jQuery 对象($)传递来帮助避免与其他基于 JavaScript 的库发生冲突。

DOMReady函数中,我们只需在表示选项卡容器元素的 jQuery 对象上调用tabs()小部件方法(具有idmyTabs<ul>)。当我们在浏览器中运行此文件时,我们应该看到选项卡的外观与本章第一张截图中显示的一样(当然没有注释)。

为选项卡小部件添加样式

使用火狐浏览器的 Firebug(或其他通用 DOM 探查器),我们可以看到各种类名添加到不同的底层 HTML 元素中。让我们简要回顾这些类名,并看看它们如何对小部件的整体外观产生影响。以下类名被添加到外部容器<div>中:

类名 目的
ui-tabs 允许应用特定于标签的结构 CSS。
ui-widget 设置嵌套元素继承的通用字体样式。
ui-widget-content 提供主题特定的样式。
ui-corner-all 对容器应用圆角。

容器中的第一个元素是<ul>元素。这个元素获取以下类名:

类名 目的
ui-tabs-nav 允许应用特定于标签的结构 CSS。
ui-helper-reset 中和应用到<ul>元素的浏览器特定样式。
ui-helper-clearfi 应用清除浮动,因为这个元素有浮动的子元素。
ui-widget-header 提供特定主题的样式。
ui-corner-all 应用圆角。

构成tab标题的单独<li>元素有以下类名:

类名 目的
ui-state-default 将标签标题应用为标准状态,非活动,非选择,非悬停状态。
ui-corner-top 对元素的顶边应用圆角。
ui-tabs-selected 仅应用于活动标签。在默认实现页面加载时,这将是第一个标签。选择其他标签将从当前选定的标签中移除这个类,并将其应用到新选择的标签。
ui-state-active 对当前选定的标签应用特定主题的样式。这个类名将被添加到当前被选中的标签,就像之前的类名一样。有两个类名的原因是,ui-tabs-selected提供了功能性的 CSS,而ui-state-active提供了视觉上的装饰样式。

每个<li>内的<a>元素没有任何类名,但它们仍然通过框架应用了结构和特定主题的样式。

最后,包含每个标签内容的面板元素具有以下类名:

类名 目的
ui-tabs-panel 将结构性 CSS 应用于内容面板。
ui-widget-content 应用特定主题的样式。
ui-corner-bottom 对内容面板的底边应用圆角。

所有这些类都是自动添加到基础 HTML 元素中的。在编写页面或添加基本标记时,我们不需要手动添加它们。

将自定义主题应用于标签

在下一个例子中,我们可以看到如何改变标签的基本外观。我们可以用我们自己的样式规则来覆盖纯粹用于显示目的的任何规则,快速轻松地自定义,而不改变与标签功能或结构相关的规则。

在你的文本编辑器中新建一个非常小的样式表:

#myTabs { min-width: 400px; padding: 5px; border: 1px solid #636363; background: #c2c2c2 none; }
.ui-widget-header { border: 0; background: #c2c2c2 none; font-family: Georgia; }
#myTabs .ui-widget-content { border: 1px solid #aaa; background: #fff none; font-size: 80%; }
.ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #636363; background: #a2a2a2 none; }
.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #aaa; background: #fff none; }

这就是我们需要的一切。将文件保存为tabsTheme.css在你的css文件夹中。如果你将这些类名与之前页面上的表格进行比较,你会发现我们正在覆盖特定主题的样式。因为我们正在覆盖主题文件,我们需要匹配或超越theme.css中选择器的特殊性。这就是为什么有时我们会同时针对多个选择器。

在这个示例中,我们覆盖了jquery.ui.tabs.css中的一些规则。我们需要使用jquery.ui.theme.css中的选择器(.ui-widget-content),以及我们容器元素的 ID 选择器,以打败双类选择器.ui-tabs .ui-tabs-panel

tabs1.html<head>中添加对这个新样式表的引用,并将文件另存为tabs2.html

<link rel="stylesheet" href="css/tabsTheme.css">

注意

确保我们刚刚创建的自定义样式表出现在jquery.ui.tabs.css文件之后,因为如果样式表的链接顺序不正确,则无法覆盖我们尝试覆盖的规则。

如果我们在浏览器中查看新页面,它应该显示如下截图:

将自定义主题应用于选项卡

我们的新主题与默认的平滑主题(如第一张截图所示)并没有明显的区别,但我们可以看到,为了适应其环境,更改小部件外观是多么容易,以及需要多少代码。

配置选项卡小部件

库中的每个不同组件都有一系列选项,用于控制小部件的哪些功能默认启用。可以将对象文字或对象引用传递给tabs()小部件方法以配置这些选项。

可用的选项来配置非默认行为如下表所示:

选项 默认值 用于...
active 0 表示打开的面板。
collapsible false 允许点击活动选项卡时取消选择它,以便隐藏所有内容面板,只显示选项卡标题。
disabled false 在页面加载时禁用小部件。我们还可以传递一个选项卡索引(从零开始)的数组,以便禁用特定的选项卡。
event "click" 指定触发内容面板显示的事件。
heightStyle content 控制选项卡小部件和每个面板的高度。可能的值是autofillcontent
hide null 控制是否以及如何动画隐藏面板。
show null 控制是否以及如何动画显示面板。

使用选项卡

选项卡小部件提供了一些选项,我们可以使用这些选项执行操作,例如选择或禁用选项卡,或添加过渡效果。在接下来的几个示例中,我们将查看其中一些选项,从选择选项卡开始。

选择选项卡

让我们看看如何使用这些可配置属性。例如,让我们配置小部件,使得页面加载时显示第二个选项卡。在tabs2.html<head>中删除tabsTheme.css的链接,并将最终的<script>元素更改为以下内容:

<script>
 $(document).ready(function($){
 var tabOpts = {
 active: 1
 };
 $("#myTabs").tabs(tabOpts);
 })
</script>

将此保存为tabs3.html。不同的选项卡及其关联的内容面板由从零开始的数字索引表示。指定默认打开的不同选项卡与提供其索引号作为active属性的值一样容易。现在页面加载时,默认应选择第二个选项卡。

除了更改选定的选项卡外,我们还可以通过为collapsible属性提供一个值来指定初始情况下不应选择任何选项卡。将tabs4.html中的<script>元素更改为以下内容:

<script>
 $(document).ready(function($){
 var tabOpts = {
 active: false,
 collapsible: true
 };
 $("#myTabs").tabs(tabOpts); 
})
</script>

这将导致小部件在页面加载时如下所示:

选择选项卡

禁用选项卡

您可能希望在满足特定条件之前禁用特定选项卡。通过操纵选项卡的disabled属性,这很容易实现。将tabs4.html中的tabOpts配置对象更改为以下内容:

var tabOpts = {
 disabled: [1]
};

将此保存为jqueryui文件夹中的tabs5.html。在此示例中,我们删除了active属性,并将第二个选项卡的索引添加到禁用数组中。我们还可以将其他选项卡的索引以逗号分隔的方式添加到此数组中,以默认禁用多个选项卡。

当页面在浏览器中加载时,第二个选项卡的类名为ui-widget-disabled,并且会应用来自ui.theme.css的禁用样式。正如下面的截图所示,它不会以任何方式响应鼠标交互:

禁用选项卡

添加转换效果

我们可以使用show属性轻松添加引人注目的转换效果。当打开或关闭选项卡时,这些效果会显示出来。此选项是使用我们的配置对象内的另一个对象文字(或数组)配置的,该对象启用一个或多个效果。例如,我们可以使用以下配置对象启用淡入淡出效果:

var tabOpts = {
 show: { effect: "toggle", duration: "slow" }
};

将此文件保存为jqueryui文件夹中的tabs6.html。我们创建的show对象具有两个属性。第一个属性是在更改选项卡时使用的动画。要使用淡入淡出动画,我们指定effect,因为这是要调整的内容。切换效果只是反转其当前设置。如果当前可见,则将其设置为不可见,反之亦然。您可以使用任何一个效果选项,例如togglefadeInslideDown;我们将在第十四章中更详细地了解效果,UI Effects

第二个属性duration指定动画发生的速度。此属性的值为slowfast,分别对应200600毫秒。任何其他字符串都将导致默认持续时间为400毫秒。我们还可以提供一个表示动画应持续的毫秒数的整数。

当我们运行文件时,我们可以看到在选项卡关闭时选项卡内容慢慢淡出,当新的选项卡打开时淡入。两个动画在单个选项卡交互期间发生。为了只在选项卡关闭时显示动画一次,例如,我们需要将show对象嵌套在数组中。将tabs6.html中的配置对象更改为以下内容:

var tabOpts = {
 show: [{ opacity: "toggle", duration: "slow" }, null]
};

当前打开的内容面板的关闭效果包含在数组的第一项中的对象中,而新选项卡的打开动画是第二项。通过将数组的第二项指定为null,我们在选择新选项卡时禁用了打开动画。将此保存为tabs7.html,并在浏览器中查看结果。

我们还可以通过在第二个数组项上添加另一个对象而不是null来指定不同的动画和速度以用于打开和关闭动画。

折叠选项卡

默认情况下,单击当前活动的选项卡时不会发生任何事情。但是我们可以更改这一点,使得当选择其选项卡标题时,当前打开的内容面板关闭。将tabs7.html中的配置对象更改为以下内容:

var tabOpts = {
 collapsible: true
};

保存此版本为tabs8.html。此选项允许关闭所有内容面板,就像在前面的selected属性中提供null时那样。单击停用的标签将选择该标签并显示其关联的内容面板。再次单击相同的选项卡会关闭它,将小部件缩小,以便只有选项卡标题可见。

使用选项卡事件

选项卡小部件定义了一系列有用的选项,允许您添加回调函数以在检测到小部件公开的特定事件时执行不同的操作。下表列出了能够在事件上接受可执行函数的配置选项:

事件 当...时触发
add 添加了一个新选项卡。
disable 选项卡已禁用。
enable 选项卡已启用。
load 选项卡的远程数据加载完毕。
remove 移除了一个选项卡。
select 选择了一个选项卡。
show 选项卡显示。

库中的每个组件都有回调选项(例如上表中的选项),它们被调整为查找任何访客交互中的关键时刻。我们在这些回调中使用的任何函数通常在更改发生之前执行。因此,您可以从回调中返回 false 并阻止操作发生。

在我们的下一个示例中,我们将看到使用标准非绑定技术如何轻松地对选择的特定选项卡作出反应。将tabs8.html中最后的<script>元素更改为以下内容:

$(document).ready(function($){
 var handleSelect = function(e, tab) {
 $("<p></p>", {
 text: "Tab at index " + tab.newTab.index() + " selected", 
 "class": "status-message ui-corner-all"
 }).appendTo(".ui-tabs-nav", "#myTabs").fadeOut(5000, function() {
 $(this).remove();
 });
 },
 tabOpts = {
 beforeActivate: handleSelect
 }
 $("#myTabs").tabs(tabOpts);
});

将此文件保存为tabs9.html。我们还需要一些 CSS 来完成这个示例。在我们刚刚创建的页面的<head>中,添加以下<link>元素:

<link rel="stylesheet" href="css/tabSelect.css">

然后,在文本编辑器的新页面中添加以下代码:

.status-message { padding:11px 8px 10px; margin:0; border:1px solid #aaa; position: absolute; right: 10px; top: 9px; font-size: 11px; background-color: #fff; }
.ui-widget-header { color: #2e6e9e; font-weight: bold; }

将此文件保存为tabSelect.css,并放在css文件夹中。在本示例中,我们在生产环境中链接了多个 CSS 文件;您可能希望考虑将 CSS 合并为一个文件,以减少 CSS HTTP 请求。尽管这将有助于在较大的站点上提高性能,但它的代价是无法替换 jQuery UI CSS 文件,因为您将丢失添加的任何自定义。

在本示例中,我们利用了beforeActivate回调来创建一个使用<p>标签的新元素,尽管原理对于标签页触发的任何其他自定义事件都是相同的。我们的回调函数名称作为我们配置对象中beforeActivate属性的值提供。

当回调函数被执行时,小部件将自动传递两个参数,即原始事件对象和包含从所选标签页中提取的有用属性的自定义对象。

要找出点击了哪个标签页,我们可以查看第二个对象的index()属性(请记住这些是从零开始的索引)。这与一些解释性文本一起添加到我们动态创建的段落元素中,并附加到小部件标题中:

使用标签页事件

每当选择一个标签页时,它前面的段落就会消失。请注意,事件在更改发生之前被触发。

绑定事件

使用每个组件公开的事件回调是处理交互的标准方法。但是,除了前面表中列出的回调之外,我们还可以在每个组件在不同时间点触发的另一组事件中插入钩子。

我们可以使用标准的 jQuery on() 方法将事件处理程序绑定到由标签页小部件触发的自定义事件,这与我们可以绑定到标准 DOM 事件(例如点击)的方式相同。

下表列出了标签小部件的自定义绑定事件及其触发器:

事件 在什么时候触发...
tabsselect 一个标签页被选中。
tabsload 远程标签页已加载。
tabsshow 显示一个标签页时。
tabsadd 一个标签页已添加到界面中。
tabsremove 一个标签页已从界面中移除。
tabsdisable 一个标签页已被禁用。
tabsenable 一个标签页已被启用。

前三个事件按顺序连续触发,即它们在表中出现的事件顺序。如果没有标签页是远程的,那么tabsbeforeactivatetabsactivate将按照此顺序触发。这些事件可以在动作发生之前或之后触发,这取决于使用哪个事件。

让我们看看这种事件使用方式的实际效果;将tabs8.html中的最后一个<script>元素更改为以下内容:

<script>
 $(document).ready(function($){
 $("#myTabs").tabs();
 $("#myTabs").on("tabsbeforeactivate", function(e, tab) {
 alert("The tab at index " + tab.newTab.index() + " was selected");
 });
 });
</script>

将此更改保存为tabs10.html。通过这种方式绑定到tabsbeforeactivate将产生与前一个示例相同的结果,使用select回调函数。与上次一样,警报应该在激活新标签页之前出现。

所有小部件公开的所有事件都可以使用on()方法,只需将小部件的名称前缀与事件的名称相结合即可。

注意

尽管每个回调名称都是使用驼峰格式拼写的,但每个事件名称必须以小写字母书写。

使用选项卡方法

选项卡小部件包含许多不同的方法,这意味着它具有丰富的行为集。它还支持实现高级功能,允许我们以编程方式使用它。让我们看一下列在下表中的方法:

方法 用于...
destroy 完全移除选项卡小部件。
disable 禁用所有选项卡。
enable 启用所有选项卡。
load 重新加载 AJAX 选项卡的内容,指定选项卡的索引号。
option 在小部件初始化后获取或设置任何属性。
widget 返回调用tabs()小部件方法的元素。

启用和禁用选项卡

我们可以使用enabledisable方法在程序中启用或禁用特定的选项卡。这将有效地启用最初被禁用的任何选项卡,或者禁用当前处于活动状态的选项卡。

让我们使用enable方法来启用默认情况下在早期示例中禁用的选项卡。在tabs5.html中现有选项卡小部件的标记之后直接添加以下新的<button>元素:

<button type="button" id="enable">Enable</button>
<button type="button" id="disable">Disable</button>

接下来,更改最后的<script>元素,使其显示如下:

<script>
$(document).ready(function($){
 $("#myTabs").tabs({
 disabled: [1]
 });
 $("#enable").click(function() {
 $("#myTabs").tabs("enable", 1);
 });
 $("#disable").click(function() {
 $("#myTabs").tabs("disable", 1);
 });
});
</script>

将更改后的文件保存为tabs11.html。在页面上,我们添加了两个新的<button>元素——一个用于启用被禁用的选项卡,另一个用于再次禁用它。

在 JavaScript 中,我们使用启用按钮的click事件调用tabs()小部件方法。为此,我们将字符串enable作为第一个参数传递给tabs()方法。此外,我们将要启用的选项卡的索引号作为第二个参数传递。jQuery UI 中的所有方法都是这样调用的。我们将要调用的方法的名称指定为小部件方法的第一个参数。disable方法的使用方式相同。不要忘记,我们可以在不需要额外参数的情况下使用这两种方法,以启用或禁用整个小部件。

添加和移除选项卡

除了在程序中启用和禁用选项卡之外,我们还可以在运行时删除它们或添加全新的选项卡。在tabs11.html中,删除现有的<button>元素,并添加以下内容:

<label>Enter a tab to remove:</label>
<input for="indexNum" id="indexNum">
<button type="button" id="remove">Remove!</button>
<button type="button" id="add">Add a new tab!</button>

然后按以下方式更改最后的<script>元素:

<script>
  $(document).ready(function($){
 $("#myTabs").tabs();
 $("#remove").click(function() {
 var indexTab = parseInt($("#indexNum").val(), 10);
 var tab = $("#myTabs").find(".ui-tabs-nav li:eq(" + indexTab + ")").remove();
 $("#myTabs").tabs("refresh");
 });
 $("#add").click(function() {
 $("<li><a href='remoteTab.txt'>New Tab</a></li>") .appendTo("#myTabs .ui-tabs-nav");
 $("#myTabs").tabs("refresh");
 });
  });
</script>

我们还需要提供一些内容,这些内容将被远程加载到选项卡中——在一个新文件中,添加远程选项卡内容!,并将其保存为remoteTab.txt

将此保存为tabs12.html——要预览此示例,您将需要使用诸如WAMP(用于 Windows)或MAMP(用于苹果 Mac)之类的本地 Web 服务器查看它。如果使用文件系统访问,演示将无法工作。

在页面上,我们添加了一个新的指令<label>,一个<input>和一个<button>,用于指定要移除的选项卡。我们还添加了第二个<button>,用于添加一个新选项卡。

<script>中,我们的第一个新函数处理删除选项卡,使用remove方法。此方法使用 jQuery 的:eq()函数查找要删除的选项卡的索引。我们获取输入到文本框中的值,并使用索引标识要删除的选项卡,然后使用refresh方法更新 Tabs 的实例。

注意

jQuery 的val()方法返回的数据格式为字符串,因此我们将调用包装在 JavaScript 的parseInt函数中以进行转换。

add方法用于向小部件添加新选项卡,其工作原理类似。在这里,我们创建了一个列表项的实例,然后使用 jQuery 的appendTo()方法将其添加到现有的选项卡中并更新它们。在此示例中,我们指定应将remoteTab.txt文件中的内容添加为新选项卡的内容。可选地,我们还可以将新选项卡应插入的索引号指定为第四个参数。如果未提供索引,则新选项卡将添加为最后一个选项卡。

添加并可能移除一些选项卡后,页面应该如下所示:

添加和删除选项卡

模拟点击

有时您可能需要以编程方式选择特定的选项卡并显示其内容。这可能是由于访问者的某些其他交互而发生的。

我们可以使用option方法来执行此操作,该方法与单击选项卡的操作完全类似。将tabs12.html中的最后一个<script>块更改为以下内容:

<script>
  $(document).ready(function($){
    $("#myTabs").tabs();
    $("#remove").click(function() {
      var indexTab = parseInt($("#indexNum").val(), 10);
      var tab = $( "#myTabs" ).find(".ui-tabs-nav li:eq(" + indexTab + ")").remove();
      $("#myTabs").tabs("refresh");
    });
    $("#add").click(function() {
      $("<li><a href='remoteTab.txt'>New Tab</a></li>").appendTo("#myTabs .ui-tabs-nav");
      $("#myTabs").tabs("refresh");
 var tabCount = $("#myTabs ul li").length;
 $("#myTabs").tabs("option", "active", tabCount - 1);
    });
 });
</script>  

将此保存为jqueryui文件夹中的tabs13.html。现在当添加新选项卡时,它将自动选中。option方法需要两个额外的参数:第一个是要使用的选项的名称,第二个是要设置为活动状态的选项卡的 ID。

由于默认情况下(尽管可以更改),我们添加的任何选项卡都将是界面中的最后一个选项卡,并且由于选项卡索引是从零开始的,因此我们只需使用length方法返回选项卡的数量,然后从该数字中减去 1 以获取索引。结果传递给option方法。

有趣的是,立即选择新添加的选项卡会修复,或者至少隐藏,来自上一个示例的额外空间问题。

销毁选项卡

如前所示,我们可以轻松添加选项卡,但在某些情况下,您可能需要完全销毁一组选项卡。这可以使用destroy方法来实现,该方法对 jQuery UI 中找到的所有小部件都是通用的。让我们看看它是如何工作的。在tabs13.html中,立即删除现有的标记,然后添加一个新的<button>如下所示:

<br>
<button type="button" id="destroy">Destroy the tabs</button>

接下来,将最后一个<script>元素更改为:

<script>
 $(document).ready(function($){
 $("#myTabs").tabs();
 $("#destroy").click(function() {
 $("#myTabs").tabs("destroy");
 });
 });
</script> 

将此文件保存为tabs14.html。我们通过单击按钮调用的destroy方法完全删除了选项卡小部件,将底层 HTML 返回到其原始状态。单击按钮后,您应该会看到一个标准的 HTML 列表元素和来自每个选项卡的文本,类似于以下屏幕截图:

销毁选项卡

注意

如果销毁选项卡,则页面中硬编码的原始选项卡将保留,而不会保留使用add方法添加的选项卡。

获取和设置选项

destroy方法一样,option方法由库中找到的所有不同组件公开。此方法用于在获取器模式和设置器模式下使用可配置选项和函数。让我们看一个基本示例;在tabs9.html中的选项卡小部件之后添加以下<button>

<button type="button" id="show">Show Selected!</button>

然后更改最后的<script>元素,使其如下所示:

<script>
$(document).ready(function($){
 $("#myTabs").tabs();
 $("#show").click(function() {
 $("<p></p>", {
 text: "Tab at index " + $("#myTabs").tabs("option", "active") + " is active"
 }).appendTo(".ui-tabs-nav").fadeOut(5000);
 });
});
</script>

我们还需要调整所显示文本的位置,因此从现有代码中删除到tabSelect.css的链接,并在<head>部分中添加以下内容:

  <style type="text/css">
    ul.ui-tabs-nav p { margin-top: 2px; margin-left: 210px;}
  </style>

将此文件保存为tabs15.html。页面上的<button>已更改,因此它显示当前活动的选项卡。我们所做的就是向状态栏消息中添加所选选项卡的索引,就像我们在早期示例中所做的那样。我们通过将字符串active作为第二个参数传递来获取active选项。可以以这种方式访问任何选项的任何值。

注意

链接 UI 方法

链接小部件方法(与其他 UI 方法或核心 jQuery 方法一起)是可能的,因为与底层 jQuery 库中的方法一样,它们几乎总是返回 jQuery($)对象。请注意,当使用返回数据的获取器方法时,例如length方法时,这是不可能的。

要触发设置器模式,我们可以提供包含我们想要设置的选项的新值的第三个参数。因此,要更改active选项的值,以更改显示的选项卡,我们可以使用以下 HTML,而不是,为此,请按照以下所示更改 HTML,在tabs15.html底部:

<br>
<label for="newIndex">Enter a tab index to activate</label>
<input id="newIndex" type="text">
<button type="button2" id="set">Change Selected</button>

接下来,按照所示添加点击处理程序:

<script>
  $(document).ready(function($){
    $("#myTabs").tabs();
 $("#set").click(function() {
 $("#myTabs").tabs("option", "active", parseInt($("#newIndex").val()));
 });
  });
</script>

将此保存为tabs16.html。新页面包含一个<label>,一个<input>,以及一个用于获取应将active选项设置为的索引号的<button>。单击按钮时,我们的代码将检索<input>的值并使用它来更改所选索引。通过提供新值,我们将该方法置于设置器模式中。

当我们在浏览器中运行此页面时,我们应该看到,通过将其索引号输入为1并单击更改所选按钮,我们可以切换到第二个选项卡。

使用 AJAX 选项卡

我们看到了如何使用 add 方法将 AJAX 选项卡动态添加到小部件中,但我们也可以使用底层 HTML 添加远程内容到选项卡。在此示例中,我们希望始终可用于显示远程内容的选项卡,并不仅限于点击按钮后。这个示例也只能在已安装和配置了 PHP 的完整 Web 服务器上正确运行,例如 WAMP(PC)或 MAMP(Macs)。

tabs16.html 中的小部件的基础 HTML 中添加以下新的 <a> 元素:

<li><a href="remoteTab.txt">AJAX Tab</a></li>

我们还应该从最后一个示例中移除 <button>

最终的 <script> 元素可用于调用 tabs 方法;不需要额外的配置:

$("#myTabs").tabs();

将其保存为 tabs17.html。我们所做的只是使用底层标记中 <a> 元素的 href 属性指定远程文件的路径(与我们在早期示例中使用的相同),从中创建选项卡。

与静态选项卡不同,我们不需要一个与链接的 href 匹配的 <div> 元素和 id。选项卡内容所需的附加元素将由小部件自动生成。

如果您使用 DOM 浏览器,您会发现我们添加的链接到远程选项卡的文件路径已被删除。相反,一个新的片段标识符已生成并设置为 href。新的片段也添加为新选项卡的 id(当然,不包括 # 符号),以便选项卡标题仍然显示选项卡。

除了从外部文件加载数据外,还可以从 URL 加载数据。当使用查询字符串或 Web 服务从数据库检索内容时,这非常有用。与 AJAX 选项卡相关的方法包括 loadurl 方法。load 方法用于加载和重新加载 AJAX 选项卡的内容,这在需要频繁刷新内容的情况下非常有用。

注意

在选项卡小部件的 AJAX 功能中没有内在的跨域支持。因此,除非额外使用 PHP 或其他服务器脚本语言作为代理,否则您可能希望利用 JavaScript Object Notation (JSON) 结构化数据和 jQuery 的 JSONP 功能。文件和 URL 应位于运行小部件的页面的同一域下。

更改远程选项卡内容的 URL

url 方法用于更改 AJAX 选项卡检索其内容的 URL。让我们看看这两种方法在实际中的简要示例。还有一些与 AJAX 功能相关的属性。

tabs17.html 中的 Tabs 小部件后添加以下新的 <select> 元素:

<select id="fileChooser">
  <option value="remoteTab1.txt">remoteTab1</option>
  <option value="remoteTab2.txt">remoteTab2</option>
</select>

然后将最终的 <script> 元素更改为以下内容:

<script>
  $(document).ready(function($){
    $("#myTabs").tabs();
    $("#fileChooser").change(function() {
      $("#myTabs").tabs("option", "active", "2");
      $("#myTabs").find("ul>li a").attr("href", $(this).val());
      $("#myTabs").tabs("load", "active");
    });
  });
</script>

将新文件保存为 tabs18.html。我们在页面中添加了一个简单的 <select> 元素,让您可以选择在 AJAX 选项卡中显示的内容。在 JavaScript 中,我们为 <select> 设置了一个 change 处理程序,并指定了在每次检测到事件时要执行的匿名函数。

此函数首先设置活动选项卡;在本例中为 AJAX 选项卡,其 ID 为 2 - 然后使用 jQuery 的 find() 方法设置选项卡面板的 href 属性,然后使用 load() 方法将内容插入选项卡中。

我们还需要一个第二个本地内容文件。更改 remoteTab1.txt 文件中的文本,并将其另存为 remoteTab2.txt

在浏览器中运行新文件,并使用 <select> 下拉列表选择第二个远程文件,然后切换到远程选项卡。第二个文本文件的内容应该会显示出来。

通过 JSONP 显示获取的数据

对于我们的最后一个示例,让我们为最后的选项卡示例拉取一些外部内容。如果我们使用选项卡小部件,结合标准的 jQuery 库的 getJSON 方法,我们可以绕过跨域排除策略,并从另一个域中拉取源,以在选项卡中显示。在 tabs19.html 中,将选项卡小部件更改为如下所示:

<div id="myTabs">
 <ul>
 <li><a href="#a"><span>Nebula Information</span></a></li>
 <li><a href="#flickr"><span>Images</span></a></li>
 </ul>
 <div id="a">
 <p>A nebulae is an interstellar cloud of dust, hydrogen gas, and plasma. It is the first stage of a star's cycle. In these regions the formations of gas, dust, and other materials clump together to form larger masses, which attract further matter, and eventually will become big enough to form stars. The remaining materials are then believed to form planets and other planetary system objects. Many nebulae form from the gravitational collapse of diffused gas in the interstellar medium or ISM. As the material collapses under its own weight, massive stars may form in the center, and their ultraviolet radiation ionizes the surrounding gas, making it visible at optical wavelengths.</p>
 </div>
 <div id="flickr"></div>
</div>

接下来,将最后的 <script> 更改为以下内容:

<script>
  $(document).ready(function($){
    var img = $("<img/>", {
      height: 100,
      width: 100
    }),
  tabOpts = {
  beforeActivate: function(event, ui) { 
    $('#myTabs a[href="#flickr"]').parent().index() != -1 ? getData() : null;
    function getData() {
      $("#flickr").empty();
      $.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?tags=nebula&format=json&jsoncallback=?", function(data) {
          $.each(data.items, function(i,item){
            img.clone().attr("src", item.media.m) .appendTo("#flickr");
            if (i == 5) {
              return false;
            }
          });
        });
      }
    }
  };
  $("#myTabs").tabs(tabOpts);
});
</script>

将文件保存为 tabs19.html 到你的 jqueryui 文件夹中。我们首先创建一个新的 <img> 元素并将其存储在一个变量中。我们还创建一个配置对象并向其添加 select 事件选项。每当选中一个标签时,我们设置为该选项值的函数将检查是否选中了一个具有 idflickr 的标签。如果是,则使用 jQuery 的 getJSON 方法从 www.flickr.com 检索图像源。

数据返回后,首先清空Flickr标签的内容,以防止图像堆积,然后使用 jQuery 的 each() 实用方法来迭代返回的 JSON 中的每个对象,并创建我们存储的图像的克隆。

每个图像的新副本都使用当前 feed 对象的信息设置其 src 属性,然后添加到空的Flickr标签中。一旦对 feed 中的六个对象进行了迭代,我们就退出了 jQuery 的 each 方法。就是这么简单。

当我们查看页面并选择图像选项卡后,经过短暂的延迟,我们应该会看到六张新图像,如下面的截图所示:

通过 JSONP 显示获取的数据

摘要

选项卡小部件是一种极好的节省页面空间的方法,通过将相关(甚至完全不相关)的内容部分组织起来,可以通过访问者的简单点击输入来显示或隐藏。它还为您的网站增添了一种交互性,可以帮助改善所使用的页面的整体功能和吸引力。

让我们回顾一下本章涵盖的内容。我们首先看了一下如何只需一点点的基本 HTML 和一行 jQuery 风格的 JavaScript,就可以实现默认的选项卡小部件。

然后,我们看到了添加自己的基本样式到标签页小部件是多么容易,这样可以改变它的外观,但不改变它的行为。我们已经知道,除此之外,我们可以使用预设计的主题或使用 ThemeRoller 创建全新的主题。

然后,我们继续研究了标签页 API 公开的一系列可配置选项。借助这些选项,我们可以启用或禁用小部件支持的不同选项,例如标签页是通过单击还是其他事件选择的,以及在小部件呈现时是否禁用某些标签页。

我们花了一些时间研究如何使用一系列预定义的回调选项,允许我们在检测到不同事件时执行任意代码。我们还看到,如果需要,jQuery 的on()方法可以监听相同的事件。

在可配置选项之后,我们介绍了一系列方法,可以通过编程方式使标签页执行不同的操作,例如模拟对标签页的点击,启用或禁用标签页,以及添加或删除标签页。

我们简要地了解了标签页小部件支持的一些更高级功能,如 AJAX 标签页,以及使用 JSONP 获取信息。这两种技术都很容易使用,并且可以为任何实现增加价值。

在下一章中,我们将继续研究手风琴小部件,类似于标签页小部件,用于将内容分组到相关部分,一次显示一个部分。

第四章:手风琴小部件

手风琴小部件是另一个 UI 小部件,允许您将内容分组到可以通过访问者交互打开或关闭的单独面板中。因此,大部分内容最初都是从视图中隐藏的,就像我们在上一章中看到的选项卡小部件一样。

每个容器都有一个与之关联的标题元素,用于打开容器并显示内容。当单击标题时,其内容将以动画形式滑入视图下方。当前可见的内容被隐藏,当我们单击手风琴标题时,新内容被显示。

在本章中,我们将涵盖以下主题:

  • 手风琴小部件的结构

  • 手风琴的默认实现

  • 添加自定义样式

  • 使用可配置的选项来设置不同的行为

  • 使用控制手风琴的方法

  • 内置的动画类型

  • 自定义手风琴事件

手风琴小部件是一个强大且高度可配置的小部件,允许您通过在任何时候仅显示单个内容面板来节省网页空间。

下图显示了手风琴小部件的一个示例:

手风琴小部件

对于我们的访问者来说易于使用,对于我们来说易于实现。它具有一系列可配置的选项,可用于自定义其外观和行为,并公开一系列方法,允许您以编程方式控制它。它还带有丰富的交互事件集,我们可以用来挂钩我们的访问者与小部件之间的关键交互。

手风琴容器元素的高度将自动设置,以便在标题之外还有足够的空间来显示最高的内容面板。此外,默认情况下,小部件的大小将保持固定,因此在打开或关闭内容面板时不会将页面上的其他元素推到一边。

结构化手风琴小部件

让我们花点时间熟悉一下手风琴的基本标记。在外部容器内是一系列链接。这些链接是手风琴内的标题,每个标题都会有一个对应的内容面板,在点击标题时打开。

值得记住的是,在使用手风琴小部件时一次只能打开一个内容面板。在文本编辑器中的空白页上,创建以下页面:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Accordion</title>  
  <link rel="stylesheet" href="development-bundle/themes/redmond/jquery.ui.all.css">
  <script src="img/jquery-2.0.3.js"></script>
  <script src="img/jquery.ui.core.js"></script>
  <script src="img/jquery.ui.widget.js"> </script>  
  <script src="img/jquery.ui.accordion.js"> </script>
  <script>
    $(document).ready(function($) {
      $("#myAccordion").accordion();
    });
  </script>
</head>
<body>
  <div id="myAccordion">
    <h2><a href="#">Header 1</a></h2>
    <div>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean sollicitudin. Sed interdum pulvinar justo.
    Nam iaculis volutpat ligula. Integer vitae felis quis diam laoreet ullamcorper.</div>

    <h2><a href="#">Header 2</a></h2>
    <div>Etiam tincidunt est vitae est. Ut posuere, mauris at sodales rutrum, turpis tellus fermentum metus, ut
    bibendum velit enim eu lectus. Suspendisse potenti.</div>

    <h2><a href="#">Header 3</a></h2>
    <div>Donec at dolor ac metus pharetra aliquam. Suspendisse purus. Fusce tempor ultrices libero. Sed
    quis nunc. Pellentesque tincidunt viverra felis. Integer elit mauris, egestas ultricies, gravida vitae,
    feugiat a, tellus.</div>
  </div>
</body>
</html>

将文件保存为accordion1.html,放在jqueryui文件夹中,并在浏览器中尝试运行。该小部件应该与本章开头的屏幕截图一样,完全皮肤化并准备好使用。

以下列表显示了小部件所需的依赖关系:

  • jquery.ui.all.css

  • jquery-2.0.3.js

  • jquery.ui.core.js

  • jquery.ui.widget.js

  • jquery.ui.accordion.js

正如我们在标签小部件中看到的,每个小部件都有其自己的源文件(尽管它可能依赖于其他文件来提供功能);这些必须按正确的顺序引用,以使小部件正常工作。 jQuery 库必须始终首先出现,然后是jquery.ui.core.js文件。之后,必须跟随包含所需依赖项的文件。这些文件应在引用小部件的 on-script 文件之前出现。如果文件没有按正确的顺序加载,则库组件将无法按预期的方式工作。

用于手风琴的底层标记是灵活的,小部件可以由各种不同的结构构建。在这个例子中,手风琴标题由包裹在<h2>元素中的链接组成,内容面板是简单的<div>元素。

要使手风琴正常工作,每个内容面板应该直接出现在其对应的标题之后。所有小部件的元素都被封装在一个<div>容器中,该容器被accordion()小部件方法所选中。

在从库中获取所需的脚本依赖项之后,我们使用自定义<script>块将底层标记转换为手风琴。

要初始化小部件,我们使用一个简单的 ID 选择器$("#myAccordion"),指定包含小部件标记的元素,然后在选择器后面链式调用accordion()小部件方法来创建手风琴。

在这个例子中,我们在标签标题元素中使用空片段(#)作为href属性的值,例如:

<h2><a href="#">Header 1</a></h2>

你应该注意,默认情况下,单击手风琴标题时不会跟随任何为手风琴标题提供的 URL。

与我们在上一章中看到的标签小部件类似,当小部件被初始化时,被转换为手风琴的底层标记具有一系列的类名添加到其中。

一些组成小部件的不同元素被赋予rolearia-属性。

注意

可访问的丰富互联网应用程序ARIA)是确保丰富互联网应用程序对辅助技术保持可访问性的 W3C 推荐。

最初从视图中隐藏的手风琴面板被赋予aria-expanded="false"属性,以确保屏幕阅读器不会丢弃或无法访问使用display: none隐藏的内容。这使得手风琴小部件高度可访问;它阻止读者不必要地浏览可能被隐藏的大量内容,并告诉用户他们也可以展开或折叠面板,具体取决于aria-expanded属性的当前值。

为手风琴添加样式

ThemeRoller 是选择或创建手风琴小部件主题的推荐工具,但有时我们可能希望在 ThemeRoller 无法实现的情况下,大幅改变小部件的外观和样式。在这种情况下,我们可以自定义样式我们自己的手风琴—在我们的示例中,我们将拉平样式效果,添加边框,并从手风琴小部件中的一些元素中移除角落。

在您的文本编辑器中的新文件中添加以下代码:

#myAccordion { width: 400px; border: 1px solid #636363; padding-bottom: 1px; }
#myAccordion .ui-state-active { background: #fff; } 
.ui-accordion-header { border: 1px solid #fff; font-family:
  Georgia; background: #e2e2e2 none; }
.ui-widget-content { font-size: 70%; border: none; }
.ui-corner-all { border-radius: 0; }
.ui-accordion .ui-accordion-header { margin: 0 0 -1px; } 

将此文件保存为accordionTheme.css,放在 css 文件夹中,并在accordion1.html<head>元素中的 jQuery UI 样式表之后链接到它:

<link rel="stylesheet" href="css/accordionTheme.css">

将新文件保存为accordion2.html,放在jqueryui文件夹中,并在浏览器中查看。它应该看起来像下面这样:

为手风琴设置样式

如前面的截图所示,我们已禁用了主题文件添加的内置圆角,并设置了替代字体、背景颜色和边框颜色。我们并没有大幅度更改小部件,但我们也没有使用许多样式规则。通过这种方式继续覆盖规则来构建一个更复杂的自定义主题将会很容易。

配置手风琴

手风琴具有一系列可配置选项,允许我们更改小部件的默认行为。下表列出了可用选项、它们的默认值,并简要描述了它们的用法:

选项 默认值 使用
active first child(第一个面板是打开的) 在页面加载时设置活动标题。
animate {} 控制面板的动画效果。
collapsible false 允许同时关闭所有内容面板。
disabled false 禁用小部件。
event "click" 指定触发打开抽屉的标题上的事件。
header "> li >:first-child,> :not(li):even" 设置标题元素的选择器。尽管看起来复杂,但这是一个标准的 jQuery 选择器,只是简单地针对每个奇数<li>元素中的第一个子元素。
heightStyle "auto" 控制手风琴和每个面板的高度
icons 'header': 'ui-icontriangle-1-e', 'headerSelected': 'uiicon- triangle-1-s' 指定标题元素和选定状态的图标。

更改触发事件

大多数选项都是不言自明的,它们接受的值通常是布尔值、字符串或元素选择器。让我们使用其中一些,以便我们可以探索它们的功能。将accordion2.html中的最后一个<script>元素更改为如下所示:

<script>
  $(document).ready(function($) {
 var accOpts = {
 event:"mouseover"
 }
    $("#myAccordion").accordion(accOpts);
  });
</script>

我们不再需要在accordion2.html中添加的自定义样式表,所以继续从代码中删除以下行:

  <link rel="stylesheet" href="css/accordionTheme.css">

将这些更改保存为accordion3.html。首先,我们创建一个名为accOpts的新对象字面量,其中包含event键和mouseover值,这是我们希望用来触发打开手风琴面板的事件。我们将这个对象作为参数传递给accordion()方法,并且它覆盖了小部件的默认选项,即click

mouseover事件通常用作替代触发事件。也可以使用其他事件,例如,我们可以将keydown设置为事件,但是为了使其工作,我们希望打开的手风琴面板必须已经聚焦。您应该注意,您还可以在小部件方法中使用内联对象设置选项,而不需要创建单独的对象。使用以下代码同样有效,并且通常是编码的首选方式,这是我们在本书的其余部分中将使用的方式:

<script>
  $(function() {
 $("#myAccordion").accordion({ 
 event: "mouseover" 
 });
  });
</script>

更改默认活动头

默认情况下,手风琴的第一个标题在小部件呈现时将被选中,并显示其内容面板。我们可以使用active选项在页面加载时更改选定的标题。将accordion3.html中的配置<script>块更改为以下内容:

  <script>
    $(document).ready(function($) {
      $("#myAccordion").accordion({
        active: 2
      });
    });
  </script>

将此版本保存为accordion4.html。我们将active选项设置为整数2,以默认打开第三个内容面板,并且与我们在上一章中看到的选项标题类似,手风琴的标题使用从零开始的索引。除了整数,此选项还接受 jQuery 选择器或原始 DOM 元素。

我们还可以使用布尔值false来配置手风琴,以使默认情况下不打开任何内容面板。再次更改配置对象如下:

  <script>
    $(document).ready(function($) {
      $("#myAccordion").accordion({
 collapsible: true, 
 active: false
      });
    });
  </script>

注意

如果使用active: false选项,必须还包括collapsible选项,该选项必须设置为true才能使active正确工作。

将此保存为accordion5.html。现在当页面加载时,所有内容面板都被隐藏了:

更改默认活动标题

手风琴将保持关闭状态,直到选择其中一个标题,该标题将保持打开状态,除非单击活动标题;在此时,其关联的内容面板将关闭。为了便于使用,最好避免在同一实现中同时配置此选项和mouseover事件选项,因为即使用户无意中将鼠标移到其上并再次移动,打开的面板也会关闭。

填充其容器的高度

如果设置了heightStyle选项,它将强制手风琴占据其容器的全部高度。到目前为止,我们的示例中,手风琴的容器一直是页面的主体,而页面主体的高度只能是其最大元素的高度。我们需要使用一个具有固定高度的新容器元素来查看此选项的效果。

accordion5.html<head>元素中,添加以下<style>元素:

<style>
  #container { height: 600px; width: 400px; }
</style>

然后,将手风琴的所有底层标记包装在一个新的容器元素中,如下所示:

<div id="container">
  <div id="myAccordion">
    <h2><a href="#">Header 1</a></h2>
    <div>Lorem ipsum dolor sit amet, consectetuer adipiscing   elit. Aenean sollicitudin. Sed interdum pulvinar justo. Nam iaculis volutpat ligula. Integer vitae felis quis diam laoreet ullam corper.</div>
    <h2><a href="#">Header 2</a></h2>
    <div>Etiam tincidunt est vitae est. Ut posuere, mauris at 
sodales rutrum, turpis tellus fermentum metus, ut bibendum 
velit enim eu lectus. Suspendisse potenti.</div>
     <h2><a href="#">Header 3</a></h2>
     <div>Donec at dolor ac metus pharetra aliquam. Suspendisse purus. Fusce tempor ultrices libero. Sed quis nunc. Pellentesque tincidunt viverra felis. Integer elit mauris, egestas ultricies, gravida vitae, feugiat a, tellus.</div>
  </div>
</div>

最后,更改我们自定义 <script> 元素中的配置对象,使其如下所示:

  <script>
    $(document).ready(function($) {
      $("#myAccordion").accordion({
 heightStyle: "fill" 
      });
    });
  </script>

将更改保存为 accordion6.html。使用页面 <head> 元素中指定的 CSS 为新容器指定了固定的高度和宽度。

注意

在大多数情况下,您将希望创建一个单独的样式表。对于我们的目的,只有一个选择器和两个规则,使用 HTML 文件中的样式标记最为方便。

选项 heightStyle 强制手风琴占据整个容器的高度,限制容器的宽度自然也会减小小部件的宽度。这个页面应该显示如下:

填充其容器的高度

使用手风琴动画

手风琴小部件附带了默认启用的内置幻灯片动画,在我们所有的示例中都存在。禁用此动画只需将 animate 选项的值设为 false 即可。从页面的 <head> 元素中删除 <style> 标签,在 accordion6.html 中删除额外的容器 <div>,然后更改配置对象,使其如下所示:

  <script>
    $(document).ready(function($) {
      $("#myAccordion").accordion({
 animate: false
      });
    });
  </script>

将其保存为 accordion7.html。这将导致每个内容面板立即打开,而不是在单击标头时漂亮地滑动打开。

小部件中还构建了另一种备用动画——EaseOutBounce 动画。然而,要使用这个备用动画,我们需要在 jquery.ui.effect.js 文件中添加一个链接。

<head> 元素顶部的 jquery.ui.accordion.js 链接后,添加以下一行代码:

<script src="img/jquery.ui.effect.js"></script>

现在,更改我们自定义 <script> 元素中的配置对象,使其如下所示:

  <script>
    $(document).ready(function($) {
      $("#myAccordion").accordion({
 animate: {
 duration: 600,
 down: {
 easing: "easeOutBounce",
 duration: 1000
 }
 }
      });
    });
  </script>

将这些更改保存为 accordion8.html。尽管手风琴面板的关闭方式与之前的示例完全相同,但在打开时,它们会在动画结束时反弹几次。这是使动画更有趣的好方法,正如我们在这个示例中看到的那样,使用起来非常简单。

除了两个预配置的动画之外,我们还可以使用 jquery.ui.effect.js 文件中定义的任何不同的缓动效果,包括以下内容:

  • easeInQuad

  • easeInCubic

  • easeInQuart

  • easeInQuint

  • easeInSine

  • easeInExpo

  • easeInCirc

  • easeInElastic

  • easeInBack

  • easeInBounce

这些缓动方法的每一个都有相应的 easeOuteaseInOut 对应方法。完整列表,请参见 jquery.ui.effect.js 文件,或参考 第十四章 中的缓动表,UI Effects

注意

jqueryui.com/accordion/ 查看 jQuery UI 演示站点,以了解一些很棒的手风琴效果示例。这些效果可以应用于任何可以进行动画处理的小部件,例如手风琴、选项卡、对话框或日期选择器。

缓动效果不会改变底层动画,仍然基于幻灯片动画。但它们确实改变了动画的进展方式。例如,我们可以通过在配置对象中使用 easeInOutBounce 缓动效果来使内容面板在动画开始和结束时都跳动:

<script>
  $(document).ready(function($) {
    $("#myAccordion").accordion({
      animate: {
        duration: 600,
        down: {
 easing: "easeInOutBounce",
          duration: 1000
        }
      }
    });
  });
</script>

将此文件保存为 accordion9.html 并在浏览器中查看。大多数缓动效果都有相反的效果,例如,我们可以使用 easeInBounce 缓动效果使内容面板在动画开始时跳动,而不是在动画结束时跳动。

对动画产生影响的另一个选项是 heightStyle 属性,在每次动画后重置 heightoverflow 样式。请记住,默认情况下启用动画,但此选项不会启用。将 accordion9.html 中的配置对象更改为以下内容:

$(document).ready(function($) {
  $("#myAccordion").accordion({
 heightStyle: "content",
    animate: {
      duration: 600,
      down: {
 easing: "easeOutBounce",
        duration: 1000
      }
    }
  });
});

将此保存为 accordion10.html。现在运行页面时,手风琴不会保持固定尺寸;它将根据每个面板中的内容量而增长或缩小。在这个示例中并没有什么区别,但是在使用动态内容时,该属性确实会发挥作用,因为在面板内容频繁更改时,我们可能并不总是知道每个面板中会有多少内容。

列出手风琴事件

手风琴公开了三个自定义事件,列在下表中:

事件 触发时...
activate 活动标题已更改。
beforeActivate 活动标题即将更改
create 小部件已创建

每次活动标题(及其关联的内容面板)更改时触发 activate 事件。它在内容面板打开动画结束时触发,或者如果禁用动画,则立即触发(但仍在激活面板更改后)。

beforeActivate 事件在选择新标题后立即触发(即在打开动画之前),或者如果动画被禁用,则在激活面板已更改之前触发。create 事件在小部件初始化后立即触发。

使用 change 事件

让我们看看如何在我们的手风琴实现中使用这些事件。在 accordion10.html 中,将配置对象更改为如下所示:

$(document).ready(function($) {
  var statustext;
  $("#myAccordion").accordion({
    activate: function(e, ui) {
      $(".notify").remove();
      Statustext = $("<div />", {
        "class": "notify",
         text: [
           ui.newHeader.find("a").text(), "was activated,",
           ui.oldHeader.find("a").text(), "was closed"
         ].join(" ")
      });
      statusText.insertAfter("#myAccordion").fadeOut(2000, function(){
        $(this).remove();
      });
    }
  });
});

将此保存为 accordion11.html。在此示例中,我们使用 activate 配置选项来指定一个匿名回调函数,该函数每当活动面板更改时都会执行。此函数会自动接收两个对象作为参数。第一个对象是 event 对象,其中包含原始的浏览器 event 对象。

第二个参数是一个对象,其中包含有关小部件的有用信息,例如激活了哪个标题元素(ui.newHeader)和被关闭的标题(ui.oldHeader)。第二个对象是一个 jQuery 对象,因此我们可以直接在它上面调用 jQuery 方法。

在此示例中,我们导航到标题中的<a>元素,并在信息框中显示其文本内容,然后将其附加到页面并在短时间后使用淡入动画移除。

供参考,ui对象还提供了有关内容面板的信息,以ui.newPanelui.oldPanel属性的形式。

一旦激活了标题并显示了其内容面板,将生成通知:

使用 change 事件

配置 beforeActivate 事件

beforeActivate事件可以以完全相同的方式使用,并且我们使用此事件指定的任何回调函数也会收到eui对象以使用。

将上一个示例中的配置对象更改为如下所示:

$(document).ready(function($) {
  var statusText;
  $("#myAccordion").accordion({
 beforeActivate: function(e, ui) {
      statusText = $("<div />", {
        "class": "notify",
        text: [ui.newHeader.find("a").text(),
          "was activated,", ui.oldHeader.find("a").text(),
          "was closed"].join(" ");
      });
      statusText.insertAfter("#myAccordion")
        .fadeOut(2000, function() {
          $(this).remove();
      });
    }
  });
});

将此保存为accordion12.html。唯一更改的是我们使用配置对象定位的属性。当我们运行页面时,我们应该发现一切都与之前完全相同,只是我们的通知是在内容面板动画之前而不是之后产生的。

还有诸如accordionactivateaccordionbeforeactivate之类的事件,可与标准 jQuery on() 方法一起使用,以便我们可以指定在手风琴配置之外执行的回调函数。使用此方式的事件处理程序可以让我们精确地响应特定事件而触发它,而不是在页面渲染在屏幕上时触发。

例如,让我们重新设计刚刚创建的演示的脚本块,以使用accordionbeforeactivate事件处理程序。如果您想改用此格式,只需用以下脚本替换accordion12.html中的<script>块-您可以在代码中看到主要更改已突出显示:

<script>
  $(document).ready(function($) {
    var statusText;
    $("#myAccordion").accordion();

 $(document).on( "accordionbeforeactivate", function(e, ui) {
      statusText = $("<div />", {
        "class": "notify",
        text: [ui.newHeader.find("a").text(), "was activated, ", ui.oldHeader.find("a").text(), "was closed"].join(" ")
      });
      statusText.insertAfter("#myAccordion")
        .fadeOut(2000, function() {
        $(this).remove();
      });
 });
  });
</script>

在此示例中,我们将beforeActivate事件处理程序从主配置调用中移出到 Accordion,并将其绑定到了文档对象;我们同样可以将其绑定到页面上的按钮或超链接等对象上。

解释手风琴方法

手风琴包括一系列方法,允许您以编程方式控制和操作小部件的行为。一些方法对库的每个组件都是通用的,例如每个小部件都使用的destroy方法。以下表列出了手风琴小部件的唯一方法:

方法 用途
refresh 重新计算手风琴面板的高度;结果取决于内容和heightStyle选项

标题激活

option方法可用于以编程方式显示或隐藏不同的抽屉。我们可以使用文本框和新按钮轻松测试此方法。在accordion12.html中,直接在手风琴后面添加以下新标记:

<label for="activateChoice">Enter a header index to activate   </label>
<input id="activateChoice">
<button type="button" id="activate">Activate</button>

现在将<script>元素更改为以下内容:

<script>
  $(document).ready(function($) {
    var drawer = parseInt($("#activateChoice").val(), 10);

 $("#myAccordion").accordion();
 $("#activate").click(function() {
 $("#myAccordion").accordion("option", "active", drawer);
 });
  });
</script>

将新文件保存为accordion13.htmloption方法需要两个额外的参数。它期望接收要使用的选项的名称,以及要激活的标题元素的索引(从零开始的)编号。在本示例中,我们通过返回文本输入的值来获得要激活的标题。我们使用 JavaScript 的parseInt()函数将其转换为整数,因为val() jQuery 方法返回字符串。

如果指定了不存在的索引号,则不会发生任何事情。如果未指定索引,则将激活第一个标题。如果指定了除整数以外的值,则不会发生任何事情;脚本将静默失败,而不会出现任何错误,并且手风琴将继续正常工作。

添加或删除面板

在 1.10 版本之前,更改手风琴中面板数量的唯一方法是销毁它并重新初始化一个新实例。虽然这样做可以,但这不是实施任何更改的满意方式,考虑到这一点,jQuery 团队努力介绍了一种新方法,该方法使其与其他小部件保持一致,这些小部件不需要重新创建即可更改任何已配置的选项。让我们使用输入按钮来测试这种方法,以创建我们的新面板。

accordion13.html中,将手风琴下面的标记更改为以下代码:

<p>
 <button type="button" id="addAccordion">Add Accordion</button>
</p>

修改<script>块,使其如下所示:

<script>
  $(document).ready(function($) {
    $("#myAccordion").accordion();
 $('#addAccordion').click( function() {
 var newDiv = "<h2><a ref='#'>New Header</a></h2><div>New Content</div>";
 $("#myAccordion").append(newDiv).accordion("refresh"); 
 });
  });
</script>

将新文件保存为accordion14.html。在本示例中,我们已经为新的手风琴面板创建了额外的标记内容,并将其分配给newDiv变量。然后我们将其附加到myAccordion <div>,然后使用手风琴的refresh方法刷新它。这不需要任何参数。

注意

我们已指定在每个手风琴面板的标记中使用的默认文本。只要保持相同的标记,就可以轻松修改为包含所需文本,这是可以的。

页面加载时,我们可以单击Add Accordion以添加任意数量的新手风琴面板,如下图所示:

添加或删除面板

但是,如果我们需要删除手风琴面板,则需要更多的工作 - 标记分为两部分(标题和面板),因此我们必须分别删除两者。修改手风琴下面的标记:

<p>  
  <label>Enter a tab to remove:</label>
  <input for="indexNum" id="indexNum">
  <button type="button" id="remove">Remove!</button>
</p>

现在将<script>块更改如下:

<script>
  $(document).ready(function($) {
    function removeDrawer(removeIndex) {
      $("#myAccordion").find("h2").eq(removeIndex).remove();
      $("#myAccordion").find("div").eq(removeIndex).remove();
      $("#myAccordion").accordion("refresh");   
    }
    $("#myAccordion").accordion();
    $("#remove").click(function(event, ui) {
      var removeIndex = $("#indexNum").val();
      removeDrawer(removeIndex);
    });
  });
</script>

将新文件保存为accordion15.html;页面加载时,输入1并单击Remove以删除中间标题及其面板:

添加或删除面板

在本示例中,我们通过返回文本输入的值来获取要删除的手风琴。如果指定了不存在的索引号,则不会发生任何事情。

然后,我们使用eq()根据给定的值查找要删除的标题和面板,一旦找到,它们就会被删除。最后一步是refresh手风琴,以便然后可以选择新的标题和面板。

调整手风琴面板的大小

修改accordion10.html中手风琴小部件的基础标记,以便第三个标题指向一个远程文本文件,第三个面板为空。标题元素还应该有一个id属性:

<div id="myAccordion">
  <h2><a href="#">Header 1</a></h2>
  <div>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean sollicitudin. Sed interdum pulvinar justo. Nam iaculis volutpat ligula. Integer vitae felis quis diam laoreet ullamcorper.</div>
  <h2><a href="#">Header 2</a></h2>
  <div>Etiam tincidunt est vitae est. Ut posuere, mauris at sodales rutrum, turpis tellus fermentum metus, ut bibendum velit enim eu lectus. Suspendisse poten-ti.</div>
 <h2 id="remote"><a href="remoteAccordion.txt">Remote</a></h2>
 <div></div>
</div>

您将在代码中看到,我们已经引用了一个文本文件,该文件将托管我们的远程内容。在编辑器中新建一个文件,添加一些虚拟文本,并将其保存为remoteAccordion.txt。 (此书附带的代码下载中提供了此文件的副本)。

然后将最终的<script>元素更改为以下形式:

$(document).ready(function($) {
  $("#myAccordion").accordion({
    beforeActivate: function(e, ui) {
      if (ui.newHeader.attr("id") === "remote") {
        $.get(ui.newHeader.find("a").attr("href"),
        function(data) {
          ui.newHeader.next().text(data);
        });
      }
    },
    activate: function(e, ui) {      
      ui.newHeader.closest("#myAccordion").accordion("refresh");
    }
  });
});

将此文件保存为accordion16.html。要正确查看此示例,您需要安装本地 Web 服务器,如 WAMP(对于 PC)或 MAMP(Mac),否则将不会呈现remoteAccordion.txt文件的内容。

在我们的配置对象中,我们使用beforeActivate事件来检查元素的id是否与我们给远程手风琴标题的id匹配。

如果是这样,我们使用 jQuery 的get()方法获取<a>元素的href属性中指定的文本文件的内容。如果请求成功返回,我们在标题之后将文本文件的内容添加到空面板中。所有这些都发生在面板打开之前。

然后我们使用activate事件在面板打开后调用手风琴的refresh方法。

当我们在浏览器中运行页面时,远程文本文件的内容应足以导致内容面板内出现滚动条。调用refresh方法可以使小部件重新调整自身,以便它可以容纳所有新添加的内容而不显示滚动条。

从代码中可以看出,我们在两个地方使用了newHeader属性;一个是作为加载内容的一部分,另一个是刷新面板一旦内容被添加后。让我们探讨一下这一点,因为这是我们如何访问任何手风琴中的内容的关键部分。

ui对象包含四个属性,允许我们访问已添加到页面上的任何手风琴的标题或面板中的内容。完整列表如下:

标题 …中的内容访问
ui.newHeader 刚刚激活的标题
ui.oldHeader 刚刚停用的标题
ui.newPanel 刚刚激活的面板
ui.oldPanel 刚刚停用的面板

一旦我们引用了相关的面板或标题,我们就可以自由地自行操作内容。

手风琴的互操作性

手风琴小部件是否与库中的其他小部件很好地协作?让我们看一看手风琴是否可以与上一章的小部件——选项卡小部件结合使用。

修改手风琴的基础标记,以便第三个内容面板现在包含选项卡的标记,并且第三个标题不再指向远程文本文件:

<div id="myAccordion">
  <h2><a href="#">Header 1</a></h2>
  <div>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean sollicitudin. Sed interdum pulvinar justo.Nam iaculis volutpat ligula. Integer vitae felis quis diam laoreet ullamcorper.</div>
  <h2><a href="#">Header 2</a></h2>
  <div>Etiam tincidunt est vitae est. Ut posuere, mauris at sodales rutrum, turpis tellus fermentum metus, ut bibendum velit enim eu lectus. Suspendisse potenti.</div>
  <h2><a href="#">Header 3</a></h2>
  <div>
 <div id="myTabs">
 <ul>
 <li><a href="#0"><span>Tab 1</span></a></li>
 <li><a href="#1"><span>Tab 2</span></a></li>
 </ul>
 <div id="0">This is the content panel linked to the first tab, it is shown by default.</div>
 <div id="1">This content is linked to the second tab and will be shown when its tab is clicked.</div>
 </div>
  </div>
</div>

我们还应该在手风琴的源文件之后链接到选项卡小部件的源文件;在您的代码中,在对jquery.ui.widget.js的调用下方立即添加此行:

<script src="img/jquery.ui.tabs.js"></script>  

接下来,将最后一个<script>元素更改为以下内容:

  <script>
    $(document).ready(function($) {
 $("#myAccordion").accordion();
 $("#myTabs").tabs();
    });
  </script>

将此文件保存为accordion17.html。我们对此文件所做的所有操作只是向手风琴的一个内容面板添加了一个简单的选项卡结构。在页面末尾的<script>元素中,我们只调用手风琴和选项卡的小部件方法。不需要额外或特殊的配置。

当第三个手风琴标题被激活时,页面应该如下所示:

手风琴互操作性

小部件也是兼容的,也就是说,我们可以在选项卡的内容面板中包含一个手风琴而不会产生任何负面影响。

使用多个手风琴

我们已经看到如何在页面上轻松使用手风琴与其他小部件。那么在同一页上使用多个手风琴呢?同样也不是问题;我们可以在同一页上拥有多个手风琴,只要我们正确地配置对手风琴的调用(s)即可。

在您的文本编辑器中,在accordion1.html的现有块之下立即添加以下标记:

  <p>
  <div class="myAccordion two">
    <h2><a href="#">Header 1</a></h2>
    <div>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean sollicitudin. Sed interdum pulvinar justo. Nam iaculis volutpat ligula. Integer vitae felis quis diam laoreet ullamcorper.
    </div>
    <h2><a href="#">Header 2</a></h2>
    <div>Etiam tincidunt est vitae est. Ut posuere, mauris at sodales rutrum, turpis tellus fermentum metus, ut bibendum velit enim eu lectus. Suspendisse potenti.
</div>
    <h2><a href="#">Header 3</a></h2>
    <div>Donec at dolor ac metus pharetra aliquam. Suspendisse purus. Fusce tempor ultrices libero. Sed quis nunc. Pellentesque tincidunt viverra felis. Integer elit mauris, egestas ultricies, gravida vitae,
    feugiat a, tellus.</div>
  </div>  

我们需要在我们的代码中允许第二个手风琴小部件,因此请按如下方式调整<script>块:

  <script>
    $(document).ready(function($) {
 $(".myAccordion").accordion();
 $( ".two" ).accordion( "option", "icons", { "header": "ui-icon-plus", "activeHeader": "ui-icon-minus" } ); 
    });
  </script>

将文件保存为accordion18.html。如果我们在浏览器中预览结果,应该会看到如下内容:

使用多个手风琴

我们所做的只是复制第一个手风琴的现有标记;关键是如何在我们的脚本中启动第二个手风琴功能。

在本书中,我们已经使用选择器 ID 来启动我们的手风琴;这是完美的,特别是当页面上只有一个手风琴时。如果在同一页(甚至是同一个网站)上有多个手风琴,这可能会变得笨拙,因为我们不必要地重复代码。

我们可以通过切换到使用类来解决这个问题,而不是使用选择器 ID,手风琴可以很容易地使用两种方法中的任何一种。在我们的示例中,我们为两个手风琴都分配了一个类名.myAccordion。然后,我们在脚本中使用它来初始化对.accordion()的调用。这允许我们在多个手风琴中共享通用功能,而不会重复代码。

如果我们需要覆盖其中一个或多个手风琴的配置,我们可以通过将第二个单独的类添加到我们的标记中来实现这一点,在这种情况下,我们希望更改第二个手风琴以使用+图标,而不是箭头。

为了实现这一点,第二个手风琴被分配了.myAccordion .two类。然后,第二个类被用作调用第二个accordion()实例的基础;这会覆盖原始配置,但仅适用于那些被分配了额外.two类的手风琴。然后,我们可以通过向手风琴的标记中添加第二个类来扩展这个原则,以使任何其他应具有不同功能的手风琴也适用于此原则。

摘要

我们首先了解了手风琴的作用以及它如何被 CSS 框架所针对。然后,我们继续查看了可配置选项,这些选项可用于更改手风琴的行为,比如指定默认打开的替代标题,或设置触发内容抽屉打开的事件。

除了可配置选项,我们还发现手风琴暴露了几个自定义事件。通过使用它们,我们可以在配置期间指定回调函数,或者在配置后绑定到它们,以在小部件发生不同事情时执行额外功能。

接下来,我们看了手风琴的默认动画以及如何使用缓动效果来实现内容面板的展开动画。我们发现,要使用非标准的动画或缓动效果,需要将jquery.ui.effect.js文件与所需的自定义效果文件一起包含进来。

除了查看这些选项之外,我们还发现手风琴可以调用一系列方法来在程序中控制它的行为。在下一章中,我们将开始使用对话框小部件,这使我们能够创建一个灵活的、高度可配置的浮动层,该层浮动在页面上方并显示我们指定的任何内容。

第五章:对话框

传统上,显示简短消息或询问访问者问题的方法是使用 JavaScript 的本机对话框之一(如alertconfirm),或者打开一个具有预定义大小且样式设计成对话框样式的新网页。

不幸的是,我相信你也清楚,这些方法对于我们作为开发人员并不特别灵活,对我们的访问者也不特别引人入胜。它们解决了一些问题,但通常也会引入几个新问题。

对话框小部件可以让我们显示消息、补充内容(如图像或文本)甚至交互式内容(如表单)。也很容易添加按钮,例如简单的确定取消按钮,并为它们定义回调函数以便对它们的点击作出反应;对话框也可以是模态的或非模态的。

在本章中,我们将涵盖以下主题:

  • 创建基本对话框

  • 使用对话框选项

  • 模态性

  • 启用内置动画

  • 向对话框添加按钮

  • 使用对话框回调

  • 控制对话框的程序化方法

以下截图显示了对话框小部件及其所包含的不同元素:

对话框

创建基本对话框

对话框具有许多内置的默认行为,但只需要少量方法来程序化地控制它,使其成为一个易于使用的小部件,同时也具有高度可配置性和强大性。

生成小部件很简单,只需要最小的底层标记结构。以下页面包含实现对话框小部件所需的最小标记:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Dialog</title>
  <link rel="stylesheet" href="development-bundle/themes/redmond/jquery.ui.all.css">
  <script src="img/jquery-2.0.3.js"></script>
  <script src="img/jquery.ui.core.js"></script>
  <script src="img/jquery.ui.widget.js"> </script>
  <script src="img/jquery.ui.position.js"> </script>
  <script src="img/jquery.ui.dialog.js"> </script>
  <script src="img/jquery.ui.button.js"> </script>
  <script>
    $(document).ready(function($){
      $("#myDialog").dialog();
    });
  </script>
</head>
<body>
  <div id="myDialog" title="This is the title!">
  Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Aenean sollicitudin. Sed interdum pulvinar justo. Nam iaculis volutpat ligula. Integer vitae felis quis diam laoreet ullamcorper. Etiam tincidunt est vitae est.
  </div>
</body>
</html>

将此文件保存为dialog1.html,放在jqueryui项目文件夹中。要使用对话框,需要以下依赖项:

  • jquery.ui.all.css

  • jquery.ui.core.js

  • jquery.ui.widget.js

  • jquery.ui.position.js

  • jquery.ui.dialog.js

  • jquery.ui.button.js

可选地,我们还可以包含以下文件来使对话框可拖动和可调整大小:

  • jquery.ui.mouse.js

  • jquery.ui.draggable.js

  • jquery.ui.resizable.js

对话框小部件的初始化方式与我们已经了解的其他小部件相同,通过调用小部件的插件方法。

当您在浏览器中运行此页面时,您应该看到默认的对话框小部件,如下截图所示:

创建基本对话框

与我们之前介绍的小部件一样,CSS 框架中的各种类名被添加到小部件中的不同元素中,以使它们具有各自元素的适当样式,并且所需的任何附加元素都是即时创建的。

第一个示例中的对话框在大小和位置上都是固定的,并且将被定位在视口的中心。我们可以很容易地使小部件可拖动、可调整大小或两者兼具。我们只需要在<head>的末尾与其他<script>资源一起包含可拖动和可调整大小组件的源文件,以及鼠标工具。

不重要的是,在对话框的源文件之前将可拖动和可调整大小的文件包含在页面中。它们可以出现在对话框的源文件之前或之后,小部件仍将继承这些行为。任何所需的样式,例如出现在对话框左下角的调整大小指示器,将自动从主 CSS 文件中捡取。

dialog1.html的关闭</head>标签之前直接添加以下三个<script>元素:

<script src="img/jquery.ui.mouse.js">
</script>
<script src="img/jquery.ui.draggable.js">
</script>
<script src="img/jquery.ui.resizable.js">
</script>

将其保存为dialog2.html并在浏览器中查看。现在对话框应该是可拖动的,并且可以移动到视口的任何部分,但是如果小部件移动到边缘,它不会导致滚动。

对话框还应该是可调整大小的——通过单击并按住任何角落并拖动,可以使小部件变大或变小。如果对话框比视口大,它将导致窗口滚动。

列出对话框选项

选项对象可用于对话框的小部件方法中配置各种对话框选项。让我们来看看可用的选项:

选项 默认值 描述
appendTo "body" 确定对话框(和遮罩,如果是模态的)应追加到哪个元素。
autoOpen true 当设置为true时,调用dialog()方法时立即显示对话框。
buttons {} 提供一个包含要与对话框一起使用的按钮的对象。每个键都成为<button>元素上的文本,每个值都是一个回调函数,在单击按钮时执行。
closeOnEscape true 如果设置为true,则按下Esc键时对话框将关闭。
dialogClass "" 为对话框设置额外的类名以进行主题设置。
draggable true 使对话框可拖动(需要使用jquery.ui.draggable.js)。
height auto 设置对话框的起始高度。
hide null 设置对话框关闭时要使用的效果。
maxHeight false 设置对话框的最大高度。
maxWidth false 设置对话框的最大宽度。
minHeight 150 设置对话框的最小高度。
minWidth 150 设置对话框的最小宽度。
modal false 在对话框打开时启用模态。
position center 设置对话框在视口中的起始位置。它可以接受一个字符串、一个字符串数组或包含对话框偏离视口顶部和左侧的确切坐标的数组(需要使用jquery.ui.position.js)。
resizable true 使对话框可调整大小(还需要jquery.ui.resizable.js)。
show null 设置对话框打开时要使用的效果。
title "" 替代在小部件的基础容器元素上指定标题属性。
width 300 设置对话框的起始宽度。

如您所见,我们有各种可配置的选项可供在实现对话框时使用。其中许多选项是布尔值、数值或基于字符串的,使它们易于在您的代码中获取和设置。

显示对话框

到目前为止,我们的示例中,对话框在页面加载后立即显示。 autoOpen 选项默认设置为 true,因此对话框将在初始化时立即显示。

我们可以更改这样,以便在发生其他事情时打开对话框,比如通过将 autoOpen 选项设置为 false 来点击按钮。将 dialog2.html 底部的最终 <script> 元素更改为以下内容:

<script>
  $(document).ready(function($){
 $("#myDialog").dialog({
 autoOpen: false 
 });
  });
</script>

将此保存为 dialog3.html。小部件仍然被创建;底层标记被从页面中移除,转换为小部件,然后重新附加到 <body> 的末尾。它将保持隐藏,直到调用 open 方法为止。我们稍后在本章中查看 open 方法时会回到这个选项。

设置对话框标题

选项表显示一个 title 选项,我们可以使用它来控制标题在小部件上的显示方式;如果将 draggable 属性设置为 false,则可以将其设置为可选择。虽然可以直接在代码中设置它,但在配置选项中设置它要容易得多,因为这样可以更好地控制标题在小部件中的显示方式。

默认情况下,对话框小部件的标题文本将显示为纯文本;我们可以通过向 .ui-dialog-title 类添加自定义样式来覆盖此设置。

在浏览器中,将 dialog3.html 中对话框的 <script> 块修改如下:

<script>
  $(document).ready(function($){
 $("#myDialog").dialog({
      draggable: false, 
      open: function() {
        $(".ui-dialog-title").addClass("customtitle");
      }
    });
  });
</script>

将文件保存为 dialog4.html。我们现在可以为对话框的标题栏添加一些样式 - 在一个单独的文件中添加以下代码,并将其保存为 dialogOverrides.css,在链接到 jQuery UI 样式表后:

.customtitle { color: #800080; }

如果我们在浏览器中预览结果,您可以清楚地看到标题现在以不同的颜色显示:

设置对话框标题

要查看代码的效果,我们可以查看脚本如何覆盖基本代码,使用 DOM 检查器如 Firebug:

<span id="ui-id-1" class="ui-dialog-title customtitle">This is the title!</span>

我们可以在样式表中手动为对话框元素设置样式,但这将是通过反复试验;简单地使用 jQuery 添加一个新类,然后我们可以根据自己的喜好进行样式设置,这会更容易得多!

小贴士

如果未提供值给 title 属性,则将使用对话框源元素上的属性。

配置模态选项

对话框的最大优势之一是模态性。此功能在对话框打开时创建一个覆盖在对话框下方的底层页面的覆盖层。一旦对话框关闭,覆盖层就会被移除。在对话框打开时,无法以任何方式操纵底层页面内容。

这个功能的好处是它确保对话框在基础页面再次变得交互之前关闭,并为访问者提供清晰的视觉指示,表明必须与对话框交互,然后才能继续。

修改dialog4.html中的配置对象如下所示:

    $(document).ready(function($){
      $("#myDialog").dialog({
        modal: true
      });
    });

此文件可以保存为dialog5.html。以下截图显示了模态效果(您可能需要向页面添加一些虚假内容,以充分体验模态效果):

配置模态选项

添加模态的唯一属性是modal选项。当您在浏览器中查看页面时,您将立即看到模态效果。用于创建覆盖图像的重复背景图像完全由 CSS 框架样式化,因此可以通过ThemeRoller工具进行完全主题化。如果需要,我们还可以使用自己的图像。ui-widget-overlay类名称会被添加到覆盖层中,因此这是需要覆盖的选择器,如果需要自定义的话。

添加按钮

button选项接受一个对象文字,用于指定对话框上应存在的不同<button>元素。每个property: value对表示一个单个按钮。让我们向我们的对话框添加一些<button>元素。

修改dialog5.html中的最终<script>元素,使其如下所示:

<script>
  $(document).ready(function($){
    $("#myDialog").dialog({
 buttons: { Ok: function() { }, Cancel: function() { } },
 draggable: false
    });
  });
</script>

将文件保存为dialog6.htmlbuttons对象中每个属性的关键是将形成<button>标签的文本,值是单击按钮时要执行的回调函数的名称。buttons选项可以采用对象,如此示例中的示例,也可以采用对象数组。在这个例子中,execute()cancel()函数什么都不做;我们很快就会回到这个例子并填充它们。

以下截图显示了我们的新<button>元素将如何显示:

添加按钮

小部件将在对话框底部的自己容器中添加我们的新按钮,并且如果对话框被调整大小,此容器将保持其原始尺寸。<button>元素是完全可主题化的,并且将根据使用的主题进行样式设置。

向对话框按钮添加图标

直到现在,关闭对话框通常意味着必须点击标题栏中的关闭图标-它对此目的非常有效,但并不为我们提供任何机会从浏览我们网站或在线应用程序的人那里获得响应。

在前面的示例中添加按钮有助于消除这一限制,并允许我们从最终用户处接受各种响应-我们可以通过添加图标进一步提供按钮的视觉支持。

在您的文本编辑器中,修改dialog6.html中的<script>块如下:

<script>
  $(document).ready(function($){
    $("#myDialog").dialog({
 buttons: [ { 
 text: "Ok",
 icons: { primary: "ui-icon-check", secondary: "ui-icon-circle-check" },
 click: function() { }
 }, {
 text: "Cancel",
 icons: { primary: "ui-icon-closethick", secondary: "ui-icon-circle-close" },
 click: function() { }
 } ],
      draggable: false
    });
  });
</script>

将此保存为dialog7.html。在这里,我们使用了按钮选项来指定文本、图标以及当单击按钮时应该执行的操作。您会注意到,与前一个示例相比,我们还使用了一种不同的方式来指定每个选项。两种方法都同样有效;我们需要在添加图标时使用这种方法,否则您可能会发现出现没有文本的按钮!

如果我们在浏览器中预览结果,我们现在可以看到在对话框底部出现的带有额外图标的按钮:

在对话框按钮中添加图标

图标的样式将根据使用的主题进行设置。在我们的示例中,我们指定了主要和次要图标;前者位于按钮文本的左侧,而后者位于右侧。然而,在您的应用程序或网站中,您可能只需要根据您的需求指定一个图标。

启用对话框动画

对话框为我们提供了一个内置效果,可以应用于小部件的打开或关闭(或两者)。我们只能使用一个效果,即缩放效果的实现(我们将在第十三章中更详细地介绍这一点,“使用 jQuery UI 进行选择和排序”)。将dialog7.html中的最终<script>元素更改为以下内容:

<script>
  $(document).ready(function($){
    $("#myDialog").dialog({
 show: true,
 hide: true
    });
  });
</script>

将此保存为dialog8.html。我们将hideshow选项都设置为布尔值true。这将启用内置效果,逐渐减小对话框的大小和不透明度,直到它优雅地消失。以下截图显示了效果正在进行中:

启用对话框动画

我们可以使用布尔值分别启用或禁用显示或隐藏动画,就像我们在此示例中所做的那样。我们还可以通过提供指定要使用的效果名称的字符串来指定要使用的动画类型:

<script>
  $(document).ready(function($){
    $("#myDialog").dialog({
      show: {effect: "fadeIn", duration: 1000},
      hide: {effect: "fadeOut", duration: 1000}
    });
  });
</script>

我们甚至可以更进一步,使用一些效果,比如弹跳或爆炸,尽管这些效果只有在适当时才应添加!我们稍后将在 jQuery UI 中介绍效果,第十四章中可以找到更多详细信息,“UI 效果”。您还可以在api.jqueryui.com/category/effects/上查看更多细节。

配置对话框的尺寸

与对话框大小以及其可以调整到的最小和最大尺寸相关的选项有几个。我们可以将所有这些选项添加到下一个示例中,因为它们都是相关的,以节省逐个查看它们的时间。将dialog8.html中的配置对象更改为以下内容:

$("#myDialog").dialog({
 width: 500,
 height: 300,
 minWidth: 150,
 minHeight: 150,
 maxWidth: 600,
 maxHeight: 450
});

将此文件保存为dialog9.html。这些选项对小部件的影响很简单;widthheight选项定义了对话框在首次打开时的大小,而min-max-选项分别定义了对话框可以调整到的最小或最大尺寸。

提示

另外一点需要注意的是,如果对话框过小,辅助技术和键盘用户可能会发现内容难以导航。有一个可用性原则坚持认为对话框应该始终是不可调整大小的,而窗口应该始终是可调整大小的。

虽然我认为这不是一条黑白分明、铁板一块的规则,但是将小型、信息性、基于文本的对话框保持固定大小可能是明智的,而允许包含图像和文本的内容丰富的对话框可以调整大小。我们将在第十二章中介绍如何将调整大小手柄添加到任何合适的元素(如对话框),调整大小组件中。

设置对话框的 z-index 顺序

对话框被设置为出现在任何现有页面内容的上方。我们可以使用 CSS 更改其 z-index 设置,或者通过确保正确将其附加到其父元素来提高它,以覆盖我们的现有内容。但是如果页面上有两个对话框怎么办?我们是否需要分别为每个对话框定义zIndex?焦点如何考虑?

让我们看看是否可以通过查看另一个示例来回答这些问题;将dialog7.html<body>标记更改为具有两个对话框:

<div id="dialog1" title="Dialog 1">
  Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Aenean sollicitudin. Sed interdum pulvinar justo. Nam aculis
volutpat ligula. Integer vitae felis quis diam laoreet ullamcorper. Etiam tincidunt est vitae est.
</div>
<div id="dialog2" title="Dialog 2">
  Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean sollicitudin. Sed interdum pulvinar justo. Nam iaculis volutpat ligula. Integer vitae felis quis diam laoreet ullamcorper. Etiam tincidunt est vitae est.
</div>

现在将最终的<script>元素更改为如下所示:

<script>
  $(document).ready(function($){
 $("#dialog1, #dialog2").dialog();
  });
</script>

将此文件保存为dialog10.html。我们在页面上添加了另一个对话框,它基本上只是原始对话框的一个克隆,具有不同的idtitle属性。在<script>中,我们只需在两个底层对话框容器上调用widget方法。

由于widget方法在第二个对话框上被最后调用,因此它接收焦点,第二个对话框将自动具有较高的 z-index 值。这意味着我们不需要担心单独配置它。对话框在底层标记中出现的顺序无关紧要;决定每个对话框 z-index 值的是 widget 方法的顺序。

提示

覆盖 z-index 值

如果需要覆盖 z-index 值,可以(并且应该)使用 CSS 来执行此操作-您需要使用!important属性来覆盖现有值。

由于两个对话框都没有显式设置其位置,所以当我们的示例页面加载时,只有第二个对话框会可见。然而,两者都是可拖动的,我们可以通过将第二个对话框拖离来将它们对齐,使它们略微重叠。如果我们点击第一个对话框框,它将接收焦点,因此它将显示在第二个框上方。

控制焦点

在打开对话框时,接收焦点的元素由匹配以下条件的项目确定:

  • 对话框中具有 autofocus 属性的第一个元素

  • 对话框内容中的第一个:tabbable元素

  • 对话框按钮面板中的第一个:tabbable元素

  • 对话框的关闭按钮

  • 对话框本身

以下代码摘录最能说明这一点,我们已经将autofocus属性添加到“是”单选按钮中:

  <div id="myDialog" title="Best Widget Library">
    <p>Is jQuery UI the greatest JavaScript widget library?</p>
    <label for="yes">Yes!</label>
 <input type="radio" autofocus="autofocus" id="yes" value="yes" name="question" checked="checked"><br>
    <label for="no">No!</label>
    <input type="radio" id="no" value="no" name="question">
  </div>

“是”单选按钮首先接收焦点;然后我们可以通过标签切换到小部件内的其他元素。一旦对话框关闭,焦点将自动返回到对话框打开之前具有焦点的元素。

处理对话框的事件回调

对话框小部件为我们提供了广泛的回调选项,我们可以使用这些选项在任何对话框交互中的不同点执行任意代码。以下表格列出了我们可以使用的选项:

事件 描述
beforeClose 当对话框即将关闭时触发此事件
close 当对话框关闭时触发此事件
create 当对话框初始化时触发此事件
drag 当对话框被拖动时触发此事件
dragStart 当对话框开始拖动时触发此事件
dragStop 当对话框停止拖动时触发此事件
focus 当对话框获得焦点时触发此事件
open 当对话框打开时触发此事件
resize 当对话框被调整大小时触发此事件
resizeStart 当对话框开始调整大小时触发此事件
resizeStop 当对话框停止调整大小时触发此事件

这些回调中的一些仅在特定情况下可用,例如当包含可拖动和可调整大小的 jQuery UI 组件时,才会有dragresize回调。在本章中,我们不会讨论这些回调选项,因为它们将分别在 第十一章、“拖放” 和 第十二章、“可调整大小组件” 中详细介绍。

其他回调,例如beforeClosecreateopenclosefocus将在任何实现中可用。让我们看一个使用这些回调选项的例子。

dialog10.html 页面中删除第二个对话框,然后在第一个对话框后面直接添加以下新的标记:

<div id="status" class="ui-widget ui-dialog ui-corner-all ui-widget-content">
  <div class="ui-widget-header ui-dialog-titlebar ui-corner-all">Dialog Status</div>
  <div class="ui-widget-content ui-dialog-content"></div>
</div>

现在将最终的 <script> 元素更改为以下内容:

<script>
  $(document).ready(function($){  
    $("#dialog1").dialog({
 open: function() {
 $("#status").children(":last").text("The dialog is open");
 },
 close: function() {
 $("#status").children(":last").text("The dialog is closed");
 },
 beforeClose: function() {
 if ($(".ui-dialog").css("width") > "300") {
 return false;
 }
 }
 });
  });
</script>

将此保存为 dialog11.html。该页面包含一个新的状态框,用于报告对话框是打开还是关闭。我们已经给状态框的各个元素添加了几个 CSS 框架类,以使它们与正在使用的主题相适应。

我们的配置对象使用了 openclosebeforeClose 选项来指定简单的回调函数。openclose 回调简单地相应地设置状态框的文本。在 Close 按钮在对话框上被点击之后(但在实际关闭之前)触发的 beforeClose 回调用于确定是否关闭对话框。

我们使用简单的if语句来检查对话框的宽度;如果对话框宽度大于 300 像素,则从回调中返回false,对话框保持打开状态。当然,这种行为通常在可用性方面通常是不可接受的,但它确实突出了我们如何使用beforeClose回调来阻止对话框被关闭。

页面加载时,对话框显示,并执行open回调,状态框应显示一条消息。当对话框关闭时,如下图所示,会显示不同的消息:

处理对话框的事件回调

我应该澄清的一件事是,对话框小部件只将一个对象(原始事件对象)传递给回调函数。虽然它确实将第二个ui对象传递到处理程序函数中,但在该库的此版本中,此对象不包含任何属性。

以编程方式控制对话框

对话框直观且易于使用,与库中的其他组件一样,它提供了一系列方法,用于在初始化后以编程方式控制小部件。我们可以在对话框上调用的所有方法的完整列表如下:

方法 描述
close 这用于关闭或隐藏对话框。
destroy 这用于永久禁用对话框。至于对话框的destroy方法,它与我们之前见过的其他小部件的工作方式略有不同。它不仅仅是将底层 HTML 返回到其原始状态,还会隐藏对话框。
isOpen 这用于确定对话框是否打开。
moveToTop 这用于将指定的对话框移动到堆栈顶部。
open 这用于打开对话框。
option 这用于在对话框初始化后获取或设置任何可配置选项。
widget 这用于返回调用了dialog()小部件方法的外部元素。

切换对话框

首先我们来看看如何以编程方式控制小部件的打开,可以简单地使用open方法实现。让我们重新访问dialog3.html,其中autoOpen选项设置为false,因此当页面加载时对话框不会打开。在页面上添加以下<button>

<button type="button" id="toggle">Toggle dialog!</button>

然后将以下点击处理程序添加到代码顶部的<script>块中:

$("#toggle").click(function() {
  if(!$("#myDialog").dialog("isOpen")) {
    $("#myDialog").dialog("open");
  } else {
    $("#myDialog").dialog("close");
  }
});

将此文件保存为dialog12.html。在页面上,我们添加了一个简单的<button>,可以用来打开或关闭对话框,具体取决于其当前状态。在<script>元素中,我们为<button>元素添加了一个点击处理程序,检查isOpen方法的返回值;感叹号的使用意味着我们要查看对话框是否没有打开。如果语句返回true,则对话框未打开,因此我们调用其open方法,否则我们调用close方法。

openclose 方法都会触发任何适用的事件;例如,#toggle 单击处理程序方法首先触发 beforeClose 然后是 close 事件。调用 close 方法类似于点击对话框上的关闭按钮。

从对话框获取数据

因为小部件是底层页面的一部分,所以传递数据到它和从它获取数据都很简单。对话框可以像页面上的任何其他标准元素一样对待。让我们看一个基本的例子。

在本章的早些时候,我们看过一个例子,其中向对话框添加了一些 <button> 元素。那个例子中的回调函数没有做任何事情,但是下面的例子给了我们使用它们的机会。将 dialog8.html 中的现有对话框标记替换为以下内容:

<div id="myDialog" title="Best Widget Library">
  <p>Is jQuery UI the greatest JavaScript widget library?</p>
  <label for="yes">Yes!</label>
  <input type="radio" id="yes" value="yes" name="question" checked="checked"><br>
  <label for="no">No!</label>
  <input type="radio" id="no" value="no" name="question">
</div>

现在将最终的 <script> 元素更改如下:

<script>
$(document).ready(function($){
  var execute = function(){
 var answer = $("#myDialog").find("input:checked").val();
 $("<p>").text("Thanks for selecting " + answer).
 appendTo($("body"));
 $("#myDialog").dialog("close");
 }
 var cancel = function() {
 $("#myDialog").dialog("close");
 }
  $("#myDialog").dialog({
    buttons: {
      "Ok": execute,
      "Cancel": cancel
    }
  });
});
</script>

将此保存为 dialog13.html。我们的对话框小部件现在包含一组单选按钮,一些 <label> 元素和一些文本。在这个例子中,当对话框关闭时,我们将获取所选单选按钮的结果,然后执行一些操作。

我们通过填写 execute 函数来开始 <script> 元素,该函数将作为按钮对象中 Ok 属性的值附加,稍后在脚本中。因此,每次点击 Ok 按钮时都会执行它。

在这个函数中,我们使用 :checked 过滤器来确定哪个单选按钮被选中。我们将 answer 变量的值设置为单选按钮的值,然后创建一个简短的消息,并将其附加到页面的 <body> 元素中。映射到 Cancel 按钮的回调函数很简单;我们所做的就是使用 close 方法关闭对话框。

这个例子的重点在于看到从对话框获取数据就像从页面上的任何其他元素获取数据一样简单。如果你在浏览器中预览它,你会首先看到左边的对话框;点击按钮会给出相应的响应,如下面的截图所示:

从对话框获取数据

探索对话框的互操作性

在以前的章节中,我们已经组合了多个小部件,以便我们可以看到它们如何很好地一起工作,本章也不例外。我们可以轻松地将其他 UI 小部件放入对话框中,例如我们在上一章中看到的折叠小部件。在文本编辑器中的新文件中,创建以下页面:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Dialog</title>
  <link rel="stylesheet" href="development-bundle/themes/redmond/jquery.ui.all.css">
  <script src="img/jquery-2.0.3.js"></script>
  <script src="img/jquery.ui.core.js"></script>
  <script src="img/jquery.ui.widget.js"></script>
  <script src="img/jquery.ui.position.js"></script>
  <script src="img/jquery.ui.dialog.js"></script>
  <script src="img/jquery.ui.button.js"></script>
  <script src="img/jquery.ui.accordion.js"> 
  </script>
  <script src="img/jquery.ui.mouse.js"></script>
  <script src="img/jquery.ui.draggable.js"></script>
  <script src="img/jquery.ui.resizable.js"></script>
  <script>
    $(document).ready(function($){
      $("#myDialog").dialog();
         $("#myAccordion").accordion();
    });
  </script>
</head>
<body>
  <div id="myDialog" title="An Accordion Dialog">
    <div id="myAccordion">
      <h2><a href="#">Header 1</a></h2>
      <div>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean sollicitudin.</div>
      <h2><a href="#">Header 2</a></h2>
      <div>Etiam tincidunt est vitae est. Ut posuere, mauris at so dales rutrum, turpis.</div>
      <h2><a href="#">Header 3</a></h2>
      <div>Donec at dolor ac metus pharetra aliquam. Suspendisse pu rus.</div>
    </div>
  </div>
</body>
</html>

将此文件保存为 dialog14.html。折叠小部件的基本标记被放置到对话框的容器元素中,我们只需在 <script> 元素中调用每个组件的小部件方法。

提示

在这个例子中,我们使用了相当多独立的 <script> 资源。值得记住的是,对于生产,我们应该使用组合和缩小的脚本文件,其中包含我们在下载构建器中选择的所有组件。

组合小部件应该像这样显示:

探索对话框的互操作性

创建一个动态基于图像的对话框

对话框部件背后的类是紧凑的,适用于一小部分专业行为,其中大部分我们已经了解过了。我们仍然可以通过一个动态对话框来玩一些有趣的东西,这个对话框根据触发它的元素加载不同的内容。

在文本编辑器中的新页面中,添加以下代码:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Dialog</title>
  <link rel="stylesheet" href="development-bundle/themes/redmond/jquery.ui.all.css">
  <link rel="stylesheet" href="css/dialogTheme.css">
  <script src="img/jquery-2.0.3.js"></script>
  <script src="img/jquery.ui.core.js"></script>
  <script src="img/jquery.ui.widget.js"></script>
  <script src="img/jquery.ui.position.js"></script>
  <script src="img/jquery.ui.dialog.js"></script>
  <script src="img/jquery.ui.button.js"></script>
  <script src="img/jquery.ui.accordion.js"></script>
  <script src="img/jquery.ui.mouse.js"></script>
  <script src="img/jquery.ui.draggable.js"></script>
  <script src="img/jquery.ui.resizable.js"></script>
</head>
<body>
   <div id="thumbs" class="ui-corner-all">
     <div class="ui-widget-header ui-corner-top">
       <h2>Some Common Flowers</h2>
       </div>
       <p>(click a thumbnail to view a full-size image)</p>
       <div class="thumb ui-helper-clearfix ui-widget-content">
         <a href="img/haFull.jpg" title="Helianthus annuus"><img src="img/haThumb.jpg" alt="Helianthus annuus"></a>
         <h3>Helianthus annuus</h3>
         <p>Sunflowers (Helianthus annuus) are annual plants native to the Americas, that possess a large flowering head</p>
       </div>
       <div class="thumb ui-helper-clearfix ui-widget-content">
         <a href="img/lcFull.jpg" title="Lilium columbianum"> <img src="img/lcThumb.jpg" alt="Lilium columbianum"></a>
         <h3>Lilium columbianum</h3>
         <p>The Lilium columbianum is a lily native to western North America. It is also known as the Columbia Lily or Tiger Lily</p>
       </div>
         <div class="thumb ui-helper-clearfix ui-widget-content">
         <a href="img/msFull.jpg" title="Myosotis scorpioides"> <img src="img/msThumb.jpg" alt="Myosotis scorpioides"></a>
         <h3>Myosotis scorpioides</h3>
         <p>The Myosotis scorpioides, or Forget-me-not, is a herbaceous perennial plant of the genus Myosotis.</p>
       </div>
       <div class="thumb ui-helper-clearfix ui-widget-content last">
         <a href="img/nnFull.jpg" title="Nelumbo nucifera"><img src="img/nnThumb.jpg" alt="Nelumbo nucifera"></a>
         <h3>Nelumbo nucifera</h3>
         <p>Nelumbo nucifera is known by a number of names including; Indian lotus, sacred lotus, bean of India, or simply lotus.</p>
       </div>
   </div>
   <div id="dialog"></div>
</body>
</html>

将此文件保存为dialog15.html。以下截图显示了在浏览器中预览时的结果:

创建动态基于图像的对话框

页面相对简单——我们有一个外部容器,它包围着所有内容,以及一个我们给予了类名ui-widget-header的元素。我们使用后者是为了从正在使用的主题中获取一些默认样式。

在此之后,我们有一些解释性文本,然后是一系列容器。这些容器被赋予了几个类名,其中一些是为了我们能够对其进行样式设置,而另一些(如ui-helper-clearfix)则是为了获取框架或主题样式。

在每个容器中都有一个图像,包裹在一个锚点内,一个副标题和一些描述性文本。在外部容器之后,是一个空的<div>元素,用于创建对话框。在这个例子中,我们不使用可调整大小的功能。每个缩略图都包裹在一个锚点内,以便即使禁用了 JavaScript,页面也能正常工作。在这种情况下,对话框部件不会显示,但访问者仍然可以看到每个图像的全尺寸版本。这种渐进增强形式在这种类型的应用程序中至关重要,我们始终可以查看内容。添加对话框部件的调用是为了增强对访问者的整体视图,同时确保即使禁用了 JavaScript,内容仍将显示出来!

现在,在闭合的</head>标记之前直接添加以下<script>块:

<script>
  $(document).ready(function($){
    var filename, titleText, dialogOpts = {
      modal: true,
      width: 388,
      height: 470,
      autoOpen: false,
      open: function() {
        $("#dialog").empty();
        $("<img />", { src: filename }).appendTo("#dialog");
        $("#dialog").dialog("option", "title", titleText);
      }
    };
    $("#dialog").dialog(dialogOpts);
    $("#thumbs").find("a").click(function(e) {
      e.preventDefault();
      filename = $(this).attr("href");
      titleText = $(this).attr("title");
      $("#dialog").dialog("open");
    });
  });
</script>

我们首先定义了三个变量;第一个变量用于添加被点击的缩略图的全尺寸图像的路径,第二个用于存储用作部件标题文本的图像标题,第三个是对话框的配置对象。我们已经看到了所有的配置选项都已经在实际操作中使用过了,所以我就不会详细介绍大部分选项了。

open回调,在对话框打开之前直接调用,是我们向对话框添加全尺寸图像的地方。我们首先清空对话框,然后创建一个新的<img>元素,并将其src设置为filename变量的值。然后将新的<img>附加到对话框的内部内容区域。

然后,我们使用option方法将标题选项设置为titleText变量的值。一旦定义了open回调,我们就像平常一样调用对话框的部件方法。

我们可以使用包装器<a>元素作为打开对话框的触发器。在我们的点击处理程序中,我们首先调用e.preventDefault()来阻止点击的默认操作,然后使用被点击的链接的hreftitle属性设置我们的filenametitleText变量的内容。然后,我们调用对话框的open方法来显示对话框,这将触发open选项中指定的回调函数。

提示

如果我们省略e.preventDefault(),这将覆盖对话框,浏览器将呈现每个图像,就像点击了链接一样。

对于此示例,我们还需要一个新的样式表。在文本编辑器的新页面中,添加以下代码:

#thumbs { width:342px; padding: 10px 0 10px 10px; border:1px 
   solid #ccc; background-color:#eee; }
#thumbs p { width: 330px; font-family: Verdana; font-size: 9px; 
   text-align: center; }
.thumb { width: 310px; height: 114px; padding: 10px; 
   border:1px solid #ccc; border-bottom: none; }
.last { border-bottom: 1px solid #ccc; }
.thumb img { border: 1px solid #ccc; margin-right: 10px; 
   float: left; cursor: pointer; }
.thumb h3 { margin: 0; float: left; width:198px; }
#thumbs .thumb p { width: 310px; margin:0; font-family: 
   Verdana; font-size: 13px; text-align: left; }
#thumbs .ui-widget-header { width: 330px; text-align: center; }

在前面的示例中已经使用了许多这些样式,但是为其他页面元素添加一些新规则使我们可以在实际环境中看到对话框。将此保存为dialogTheme.css,并放入css文件夹中。我们在此示例中还使用了一些图像,这些图像可以在本书的附带代码下载的img文件夹中找到。

这样现在应该给我们提供了前面截图中看到的页面,当点击缩略图时,将显示相同图像的完整尺寸版本:

创建基于图像的动态对话框

概要

对话框小部件是专门设计的,用于在悬浮面板中显示消息或问题,该面板位于页面内容之上。高级功能,如拖动和调整大小,已直接内置,并且仅需要为每个功能包含额外的脚本文件。其他功能,如出色的模态和覆盖层,易于配置。

我们首先看了默认实现,它与迄今为止我们看过的其他小部件一样简单。然后,我们检查了对话框 API 公开的一系列可配置选项。我们可以利用它们来启用或禁用内置行为,例如模态,或设置小部件的尺寸。它还为我们提供了广泛的回调,允许我们在交互期间通过小部件触发的自定义事件中挂钩。

然后,我们简要介绍了与对话框一起使用的内置打开和关闭效果,然后继续查看我们可以调用的基本方法,以执行对话框执行操作的任务,例如打开或关闭。

在下一章中,我们将继续查看滑块和进度条小部件,它们允许我们创建交互式表单小部件,用于从预定义范围中选择值并在屏幕上显示结果。

第六章:滑块和进度条小部件

滑块组件允许我们实现一个引人入胜且易于使用的小部件,我们的访问者应该会发现它吸引人且直观易用。它的基本功能很简单。滑块轨道表示一系列由沿着轨道拖动的手柄选择的值。

进度条部件用于显示任意过程的完成百分比。这是一个简单易用的组件,具有极其紧凑的 API,为访问者提供了出色的视觉反馈。

在本章中,我们将涵盖以下主题:

  • 默认的滑块实现

  • 滑块的自定义样式

  • 更改配置选项

  • 创建垂直滑块

  • 设置最小值、最大值和默认值

  • 启用多个手柄和范围

  • 滑块的内置事件回调

  • 滑块方法

  • 进度条的默认实现

  • 可配置的选项

  • 小部件公开的事件 API

  • 进度条公开的唯一方法

  • 进度条的一些真实世界示例

在我们卷起袖子开始创建滑块之前,让我们看一下它由哪些不同的元素组成。以下图示显示了一个典型的滑块小部件:

滑块和进度条小部件

正如您所见,这是一个简单的小部件,只由两个主要元素组成——滑块手柄(有时称为拇指)和滑块轨道

引入滑块部件

创建默认的基本滑块所需的代码与我们迄今为止看过的任何其他小部件一样少。所需的基本 HTML 标记也很少。现在让我们创建一个基本的滑块。在文本编辑器的新页面中,添加以下代码:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Slider</title>
  <link rel="stylesheet" href="development-bundle/themes/redmond/jquery.ui.all.css">
  <script src="img/jquery-2.0.3.js"></script>
  <script src="img/jquery.ui.core.js"></script>
  <script src="img/jquery.ui.widget.js"></script>
  <script src="img/jquery.ui.mouse.js"></script>
  <script src="img/jquery.ui.slider.js"></script>
  <script>
    $(document).ready(function($){
      $("#mySlider").slider();
    });
  </script>
</head>
<body>
  <div id="mySlider"></div>
</body>
</html>

将此文件保存为slider1.html并在浏览器中查看。页面上有一个简单的容器元素;该元素将由小部件转换为滑块轨道。在代码的<head>部分中的<script>内,我们选择此元素并在其上调用slider方法。用于滑块手柄的<a>元素将由小部件自动创建。

当我们在浏览器中运行slider1.html文件时,我们应该会看到类似于上一个图示的东西。我们为默认实现使用了几个库资源,包括以下文件:

  • jquery.ui.all.css

  • jquery-2.0.3.js

  • jquery.ui.core.js

  • jquery.ui.widget.js

  • jquery.ui.mouse.js

  • jquery.ui.slider.js

基本滑块的默认行为简单而有效。可以通过用鼠标指针拖动拇指或使用键盘上的左/下或右/上箭头键,在 x 轴上沿轨道的任何像素移动拇指。使用鼠标左键单击轨道上的任何位置将立即将手柄移动到该位置。

自定义样式

由于其简单性,很容易为滑块小部件创建自定义主题。使用 ThemeRoller 是其中一种主题化的方法:我们只需下载一个新主题,然后将其放入主题文件夹,并在代码中更改对新主题的引用名称。与所有其他小部件一样,滑块将被重新设计为使用新主题。

要完全改变小部件的外观和感觉,我们可以轻松创建自己的主题文件。在您的文本编辑器中创建以下样式表:

.background-div {
  height: 50px; width: 217px; padding: 36px 0 0 24px;
  background:  url(../img/slider_outerbg.gif) no-repeat;
}
#mySlider {
  background: url(../img/slider_bg.gif) no-repeat; height: 23px;
  width: 184px; border: none; top: 4px; position: relative; 
  left: 4px;
 }
#mySlider .ui-slider-handle {
  width: 14px; height: 30px; top: -4px;
  background: url(../img/slider_handle.gif) no-repeat;
}

将此文件保存为sliderTheme.css,放在css目录中。在slider1.html中,在页面的<head>标签中添加一个链接到样式表(在 jQuery UI 样式表之后),并将底层滑块元素包裹在一个新容器中:

<div class="background-div">
  <div id="mySlider"></div>
</div>

将此文件保存为slider2.html。只需最少量的 CSS 和几张图片(这些可以在代码下载中找到),我们就可以轻松但显著地修改小部件的外观,如下面的屏幕截图所示:

自定义样式

让我们转向如何配置滑块小部件,使用一些选项。

配置基本滑块

还可以使用对象文字配置额外的功能,例如垂直滑块、多个手柄和步进,这些功能在初始化滑块时传递到小部件方法中。可以与滑块小部件一起使用的选项列在以下表格中:

选项 默认值 用法
animate false 当单击轨道时启用滑块手柄的平滑动画。
disabled false 当初始化小部件时禁用小部件。
max 100 设置滑块的最大值。
min 0 设置滑块的最小值。
orientation auto 设置滑块手柄移动的轴。这可以接受字符串垂直或水平。
range false 在它们之间创建一个可定制样式的元素范围。
step 1 设置手柄沿轨道移动的步距。最大值必须能够被提供的数字整除。
value 0 在初始化小部件时设置滑块手柄的值。
values null 接受一个值数组。每个提供的整数将成为滑块手柄的值。

创建一个垂直滑块

要创建一个垂直滑块,我们只需将orientation选项设置为vertical;小部件将为我们完成其余工作。

slider1.html中,更改最后的<script>元素,使其如下所示:

<script>
  $(document).ready(function($){
 $("#mySlider").slider({
 orientation: "vertical"
 });
  });
</script>

将此文件保存为slider3.html。我们只需要设置这个单一选项就可以将滑块放入vertical模式。当我们启动页面时,我们会看到滑块的操作与以前完全相同,只是现在它沿着 y 轴移动,如下图所示:

创建一个垂直滑块

小部件默认高度为100px,除非我们在样式表中为.ui-slider-vertical提供自己的 CSS 规则。

设置最大值和最小值

默认情况下,滑块的最小值为0,最大值为100,但是我们可以使用minmax选项轻松更改这些值。将slider3.html中的配置对象更改为以下代码:

$("#mySlider").slider({
 min: -50,
 max: 50
});

将此文件保存为slider4.html。我们只需指定我们希望设置为起始和结束值的整数。valuevalues方法是滑块专有的,并且用于获取或设置单个或多个手柄的值。由于value选项默认设置为0,当我们运行slider4.html文件时,滑块拇指将从轨道中间开始,在-5050之间。

在此示例中,当滑块手柄位于最小值时,value方法将返回-50,正如我们所期望的那样。为了证明这一点,我们可以修改slider4.html以在警报中显示此值。在滑块配置对象的下方立即添加以下代码:

$("#getValue").click(function(){
  var value = $("#mySlider").slider("value");
  alert("Value of slider is " + value);
});

<body>标记中,将其更改如下:

  <div id="mySlider"></div>
<p>
<button id="getValue">Get value of slider</button>

如果我们现在尝试在浏览器中预览更改,当您将手柄移动到滑块的最左端时,将会弹出一个警报。我们将在本章的使用滑块方法部分中探讨value选项。

使用滑块小部件进行步进

step选项是指滑块手柄在从轨道的最小位置移动到最大位置时跳跃的步数和位置。了解此选项如何工作的最佳方法是将其实际操作,因此将slider4.html中的配置对象更改为以下代码:

$("#mySlider").slider({
 step: 25
});

将此文件保存为slider5.html。在此示例中,我们将step选项设置为25。我们尚未设置minmax选项,因此它们将采用默认值0100。因此,通过将step设置为25,我们的意思是沿着轨道的每一步应该是轨道长度的四分之一,因为100(最大值)除以25(步长值)等于4。因此,手柄将沿着轨道从头到尾走四步。

滑块的max值应该被设置为step选项设置的任何值的整数倍;除此之外,我们可以自由选择任何值。step选项对于将访问者选择的值限制在一组预定义值中非常有用。

如果我们在这个例子中将step选项的值设置为27而不是25,滑块仍然可以工作,但手柄跳转到的轨道上的点将不相等。

对滑块小部件进行动画处理

滑块小部件配有内置动画,每当单击滑块轨道时,该动画会将滑块手柄平滑地移动到新位置。此动画默认情况下是禁用的,但我们可以通过将animate选项设置为true来轻松启用它。更改slider5.html中的配置对象,使其如下所示:

$("#mySlider").slider({
 animate: true
});

将此文件保存为slider6.html。这个简单的改变可以让滑块感觉更加精致;当点击轨道时,滑块手柄不再立即移动到新位置,而是平滑地滑动到那里。

如果将step选项配置为1之外的值,并启用animate选项,则拇指将滑动到轨道上最近的步骤标记处。这可能意味着滑块拇指移动超过了被点击的点。

设置滑块的值

value选项,当在配置对象中设置为true时,确定滑块拇指的起始值。根据我们想要滑块表示的内容,手柄的起始值可能不是0。如果我们想要在轨道的中间开始而不是在开头,我们可以使用以下配置对象:

$("#mySlider").slider({
 value: 50
});

将此文件保存为slider7.html。当在浏览器中加载文件时,我们可以看到手柄从轨道中间开始,而不是从开头开始,就像我们之前设置minmax选项时一样。我们也可以在初始化后设置此选项,以编程方式设置新值。

使用多个手柄

我之前提到过滑块可能有多个手柄;可以使用values选项添加额外的手柄。它接受一个数组,数组中的每个项都是一个手柄的起始点。我们可以指定尽可能多的项,直到max值(考虑到步骤):

$("#mySlider").slider({
 values: [25, 75]
});

将此文件保存为slider8.html。这是我们需要做的一切;我们不需要提供任何额外的底层标记。小部件已为我们创建了两个新手柄,正如您将看到的,它们的功能都与标准单手柄完全相同。

下面的截图显示了我们的双手柄滑块:

使用多个手柄

我们可以利用双手柄滑块创建时间窗口以供日程安排使用。一个很好的例子是在旅行预订表格上。通常你需要手动输入日期,这可能有点笨拙。

相反,您可以使用双手柄滑块选择日期;用户只需将每个手柄向左或向右滑动以更改日期窗口。然后,我们可以使用本章前面描述的设置最小值和最大值部分中描述的方法来获取每个滑块手柄的位置值。

提示

当滑块有两个或更多手柄时,每个手柄都可以无障碍地移动到其他手柄之后;如果需要阻止此情况发生,可能需要考虑设置一个range

使用范围选项

当使用多个手柄时,我们可以将range选项设置为true。这将在两个手柄之间添加一个样式化的范围元素。在slider8.html中,更改配置对象如下:

$("#mySlider").slider({
  values: [25, 75],
 range: true
});

将此文件保存为slider9.html。当页面加载时,我们应该看到一个样式化的<div>元素现在连接了我们的两个手柄,如下面的截图所示:

使用范围选项

当使用两个手柄和一个范围时,两个手柄将无法在轨道上交叉。

最多可以使用两个手柄与range选项一起使用,但我们也可以仅启用一个手柄将上一个示例中的配置对象更改为以下内容:

$("#mySlider").slider({
 range: "min"
});

将此文件保存为slider10.html。除了布尔值true,我们还可以提供字符串值minmax中的一个,但仅当仅使用一个手柄时。

在这个例子中,我们将其设置为min,所以当我们沿着轨道移动滑块手柄时,范围元素将从轨道的起点延伸到滑块手柄。如果我们将选项设置为max,范围将从手柄延伸到轨道的末端。

如果您想要捕获手柄在刻度上的位置,我们可以通过使用slide事件处理程序来实现。在这种情况下,我们只需要获取一个值(因为我们只有一个手柄),但是如果配置了第二个手柄,同样的原则也适用。

slider4.html中,将以下函数添加到我们滑块的配置对象的上方:

function slideValues(event, ui){
  var val0 = $("#mySlider").slider("values", 0),
    endValue = parseInt(val0, 10);

  $("#rangeValues").text("Range: 0 - " + endValue);
}:

然后,我们需要修改配置对象,以在适当的时候调用我们的slideValues事件处理程序:

$("#mySlider").slider({
  range: "min",
 slide: slideValues
});

因此,我们可以在现有标记的<body>部分下方添加以下内容以在屏幕上显示结果:

<div id="rangeValues"></div>

然后,我们可以按照我们的意愿操作该值;如果你预览结果,你将看到右侧的值发生变化;左侧的值将始终保持为0,因为这是我们代码中min选项的默认值。

使用滑块的事件 API

除了我们之前看到的选项外,还有另外五个选项用于定义在滑块交互期间不同时间执行的函数。我们使用的任何回调函数都会自动传递标准事件对象和表示滑块的对象。以下表格列出了我们可以使用的事件选项:

事件 触发时…
change 滑块的手柄停止移动并且其值已更改。
create 滑块已创建
slide 滑块的手柄移动。
start 滑块的手柄开始移动。
stop 滑块的手柄停止移动。

连接到这些内置的回调函数很容易。让我们组合一个基本示例来看看。将slider10.html中的配置对象更改为如下所示:

$("#mySlider").slider({
 start: function() {
 $("#tip").fadeOut(function() {
 $(this).remove();
 });
 },
 change: function(e, ui) {
 $("<div></div>", {
 "class": "ui-widget-header ui-corner-all",
 id: "tip",
 text: ui.value + "%",
 css: { left: e.pageX-35 }
 }).appendTo("#mySlider");
 }
});

将此文件保存为slider11.html。在这个例子中,我们使用了两个回调选项——startchange。在start函数中,如果存在,我们选择提示工具元素,并使用 jQuery 的fadeOut()方法将其淡出。一旦从视图中隐藏,它将从页面中移除。

每次滑块手柄的值更改时都将执行change函数;当调用该函数时,我们创建工具提示并将其附加到滑块上。我们将其定位,使其出现在滑块手柄的中心上方,并给它一些框架类名称,以便根据使用的主题对其进行样式化。

在几个地方,我们使用传递给回调函数的第二个对象,即包含滑块有用信息的准备好的ui对象。在这个例子中,我们使用对象的value选项来获取滑块手柄的新值。

对于这个例子,我们还需要一个非常小的自定义样式表。在文本编辑器中,添加以下代码:

#mySlider { margin: 60px auto 0; }
#tip { position: absolute; display: inline; padding: 5px 0; width: 50px; text-align: center; font: bold 11px Verdana; top: -40px }

将此文件保存为css文件夹中的sliderTheme2.css,并从slider11.html<head>中添加一个链接。当显示时,我们的工具提示应该如下图所示:

使用滑块的事件 API

当所有事件选项一起使用时,事件将按以下顺序触发:

  • create

  • start

  • slide

  • stop

  • change

slide回调可能是一个相当密集的事件,因为它在每次选择手柄时都会触发鼠标移动,但它也可以通过从回调函数返回false来防止在某些情况下滑动。当同时使用stopchange回调时,change回调可能会覆盖stop回调。

与库中的所有组件一样,每个事件也可以在 jQuery 的on()方法中使用,只需在事件名前加上slider一词即可,例如,sliderstart

使用滑块方法

滑块很直观,与库中的其他组件一样,它还配备了一系列方法,用于在初始化后以编程方式控制小部件。滑块特有的方法显示在下表中:

方法 用法
value 将单个滑块手柄设置为新值。这将自动将手柄移动到轨道上的新位置。此方法接受一个参数,即表示新值的整数。
values 当使用多个手柄时,设置指定手柄移动到新值。此方法与value方法相同,只是它接受两个参数——手柄的索引号,后跟新值。

destroydisableenableoptionwidget方法对所有组件都是通用的,并且与我们期望的滑块的方式相同地工作。

正如我们在本章早些时候看到的,valuevalues方法是专门针对滑块的,并且可以用于获取或设置单个或多个手柄的值。当然,我们也可以使用option方法来实现这一点,所以这两种方法只是为了满足常见的实现需求而设置的快捷方式。让我们看看它们的作用。首先让我们看看value方法如何使用。

slider11.html中,删除对sliderTheme2.css<link>并在页面上的滑块容器后直接添加一个新的<button>元素:

<p><button type="button" id="setMax">Set to max value</button></p>

现在,更改最终的<script>元素,使其如下所示:

<script>
  $(document).ready(function($){
 $("#mySlider").slider();
 $("#setMax").click(function() {
 var maxVal = $("#mySlider").slider("option", "max");
 $("#mySlider").slider("value", maxVal);
 });
  });
</script>

将此文件保存为slider12.html。我们为新的<button>添加了一个点击处理程序;每当它被点击时,此方法将首先确定滑块的最大值,方法是通过将一个变量设置为option方法的结果来指定我们想要获取的选项为max。一旦我们有了最大值,然后我们调用value方法,传入包含最大值的变量作为第二个参数;我们的变量将被用作新值。每当按钮被点击时,滑块手柄将立即移动到轨道的末端。

提示

将值作为选项或方法使用

在本章的许多示例中,我们提到了value(或values)作为选项或方法。这可能有点令人困惑;把value方法看作是在代码中使用值选项作为 getter 的快捷方式。

使用多个手柄同样简单,但涉及略有不同的方法。

slider12.html中删除setMax按钮,并直接在滑块元素后添加以下两个按钮:

<p>
<button type="button" class="preset" id="low">Preset 1 (low) </button>
<button type="button" class="preset" id="high">Preset 2 (high) </button>

现在将<head>末尾的最后一个<script>元素更改为以下代码:

<script>
  $(document).ready(function($){
 $("#mySlider").slider({ 
 values: [25, 75] 
 });

 $(".preset").click(function() {
 if (this.id === "low") {
 $("#mySlider").slider("values", 0, 0).slider("values", 1, 25);
 } else {
 $("#mySlider").slider("values", 0, 75).slider("values" , 
 1, 100);
 }
 });
  });
</script>

将此文件保存为slider13.html。要触发多个手柄,我们在配置对象中指定了两个手柄的值。当页面上的两个<button>元素中的任何一个被点击时,我们会确定是单击了预设 1还是预设 2,然后根据点击的按钮设置手柄为低值或高值。

提示

你也可以使用数组表示法来设置滑块中的值;这将为所有手柄设置相同的值,而不管存在多少手柄。

values方法接受两个参数。第一个参数是我们想要更改的手柄的索引号,第二个参数是我们希望手柄设置的值。以下截图显示了在单击第二个按钮后页面应该显示的样子:

使用滑块方法

实际用途

HTML5 元素可能特别适合滑块小部件的实现是<audio>元素。此元素将自动添加控件,使访问者可以播放、暂停和调整正在播放的媒体的音量。

但是,默认控件无法进行样式化;如果我们希望改变它们的外观,就需要创建我们自己的控件。当然,滑块小部件是默认音量控制的绝佳替代品。让我们看看如何添加一个,作为你自己项目的基础,你可以在其中进一步发展。

在文本编辑器中创建以下新代码:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Slider</title>
  <link rel="stylesheet" href="development-bundle/themes/redmond/jquery.ui.all.css">
  <link rel="stylesheet" href="css/sliderTheme3.css">
  <script src="img/jquery-2.0.3.js"></script>
  <script src="img/jquery.ui.core.js"></script>
  <script src="img/jquery.ui.widget.js"></script>
  <script src="img/jquery.ui.mouse.js"></script>
  <script src="img/jquery.ui.slider.js"></script>
  <script>
    $(document).ready(function($){
      var audio = $("audio")[0];
      audio.volume = 0.5;
      audio.play();
      $("#volume").slider({
        value: 5,
        min: 0,
        max: 10,
        change: function() {
          var vol = $(this).slider("value") / 10;
          audio.volume = vol;
        }
      });
    });
  </script>
</head>
<body>
  <audio id="audio" controls="controls" src="img/prelude.mp3">
    Your browser does not support the <code>audio</code> element.
  </audio>
  <div id="volume"></div>
</body>
</html>

将此文件保存为slider14.html。我们还需要添加一些样式来调整显示。在文本编辑器中的新页面中添加以下内容,并将其保存为sliderTheme3.css

#volume { padding-top: 5px; }
#volume.ui-slider { width: 300px; }
.ui-slider-horizontal .ui-slider-handle { margin-left: -0.6em; top: -0.1em; }

不要忘记从主页添加到sliderTheme3.css的链接:

<link rel="stylesheet" href="css/sliderTheme3.css">

slider14.html页面上,我们有一个<audio>标记,其src属性设置为来自互联网档案馆的音频剪辑。我们还有一个空的容器元素用于我们的音量控制。

注意

这个示例使用了 Jan Morgenstern 为大兔子电影创建的音乐配乐文件之一;你可以在 archive.org/details/JanMorgenstern-BigBuckBunny 下载它以及收藏中的其他文件。

在脚本中,我们首先使用标准的 jQuery 语法选择<audio>元素,并从 jQuery 对象中检索实际的 DOM 元素,以便我们可以从<audio>API 中调用方法。

接下来,我们为我们的滑块定义配置对象并设置初始最小和最大值。然后,我们添加一个用于更改当前播放音轨音量的change事件处理程序,使用volume属性方法。每当滑块被更改时,我们都会得到一个新的滑块值,并将其转换为所需的volume属性格式,方法是将滑块值除以10。一旦我们的变量被定义,我们就设置音频剪辑的音量,并立即使用play()方法播放音频剪辑。

当我们在支持的浏览器中运行此示例时,我们可以暂停或播放音频剪辑;如果移动滑块手柄,则剪辑的音量应该增加或减少,如下图所示:

实际应用

创建一个颜色滑块

在某些应用程序中非常有用的滑块小部件的有趣实现是颜色滑块。让我们将学到的关于此小部件的知识付诸实践,制作一个基本的颜色选择工具。以下屏幕截图显示了我们将要制作的页面:

创建颜色滑块

在你的文本编辑器中,将slider1.html中的<body>标记更改为以下代码:

<div id="container" class="ui-widget ui-corner-all ui-widget-content ui-helper-clearfix">
  <label>R:</label>
  <div id="rSlider"></div><br>
  <label>G:</label>
  <div id="gSlider"></div><br>
  <label>B:</label>
  <div id="bSlider"></div>
  <div id="colorBox" class="ui-corner-all ui-widget-content"></div>
  <label for="output" id="outputLabel">Color value:</label>
  <input id="output" type="text" value="rgb(255,255,255)">
</div>

现在让我们为我们的演示添加script功能,所以请继续移除最后一个<script>元素的内容,并添加以下代码:

<script>
  $(document).ready(function($){
    $("#rSlider, #gSlider, #bSlider").slider({
      min:0,
      max: 255,
      value: 255,
      slide: function() {
        var r = $("#rSlider").slider("value"),
        g = $("#gSlider").slider("value"),
        b = $("#bSlider").slider("value");
        var rgbString = ["rgb(", r, ",", g, ",", b, ")"].join("");
        $("#colorBox").css({
          backgroundColor: rgbString
        });
        $("#output").val(rgbString);
      }
    });
  });
</script>

将此文件保存为slider15.html。页面本身非常简单。我们有一些主要用于显示颜色滑块的不同组件的元素,以及将被转换为滑块小部件的各个容器元素。我们为我们的颜色选择器使用了三个滑块,每个滑块对应一个 RGB 通道。

我们还需要一些 CSS 来完善我们小部件的整体外观。在你的文本编辑器中新建一个页面,创建以下样式表:

#container { width: 426px; height: 146px; padding: 20px 20px 0; position: relative; font-size: 11px; background: #eee; }
#container label { float: left; text-align: right; margin: 0 30px 26px 0; clear: left; }
.ui-slider { width: 240px; float: left; }
.ui-slider-handle { width: 15px; height: 27px; }
#colorBox { width: 104px; height: 94px; float: right; margin: -83px 0 0 0; background: #fff; }
#container #outputLabel { float: right; margin: -14px 34px 0 0; }
#output { width: 100px; text-align: center; float: right; clear: both; margin-top: -17px; }

将此文件保存为colorSliderTheme.csscss文件夹中;别忘了在主文件中调用 jQuery UI 样式表后立即添加对此文件的链接:

<link rel="stylesheet" href="css/colorSliderTheme.css">

在我们的代码中,我们给容器和颜色框元素分配了来自 CSS 框架的类名,这样我们就可以利用诸如圆角之类的效果,以减少我们自己编写的 CSS 量。

关注 JavaScript 代码,我们首先设置配置对象。由于 RGB 颜色值范围从0255,我们将max选项设置为255,将value选项也设置为255,这样小部件手柄就会在正确的位置开始(页面加载时,颜色框将具有白色背景)。

slide回调是行动发生的地方。每当移动一个手柄时,我们都会使用value方法更新rgb变量的值,然后从我们的变量值构造一个新的 RGB 字符串。这是必要的,因为我们不能直接将变量传递给 jQuery 的css()方法。我们还会更新<input>字段中的值。

运行示例时,我们应该发现一切都按预期工作。一旦我们开始移动任何一个滑块手柄,颜色框就开始变色,而<input>也会更新。

注意

slide事件在选定手柄后的每次鼠标移动时触发;这是一个潜在的密集型事件,在旧浏览器或慢速计算机上可能会引起问题。因此,在生产环境中使用时应谨慎,以使事件处理程序中的不必要操作最小化。

引入进度条小部件

小部件只由两个嵌套的<div>元素组成——一个外部<div>容器和一个内部<div>容器,用于突出显示当前进度。下图显示了一个完成 50%的进度条:

引入进度条小部件

让我们来看看最基本的进度条实现。在文本编辑器中的新文件中,创建以下代码:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Progressbar</title>
  <link rel="stylesheet" href="development-bundle/themes/redmond/jquery.ui.all.css">
  <script src="img/jquery-2.0.3.js"></script>
  <script src="img/jquery.ui.core.js"></script>
  <script src="img/jquery.ui.widget.js"></script>
  <script src="img/jquery.ui.progressbar.js"></script>
  <script>
    $(document).ready(function($){
      $("#myProgressbar").progressbar();
    });
  </script>
</head>
<body>
  <div id="myProgressbar"></div>
</body>
</html>

将此文件保存为jqueryui项目文件夹中的progressbar1.html。没有配置时,进度条当然是空的。我们的示例应该看起来像第一张截图,但没有显示任何进度(容器为空)。

进度条依赖以下组件:

  • jquery.ui.all.css

  • jquery-2.0.3.js

  • jquery-ui.core.js

  • jquery-ui.progressbar.js

页面上所需的全部就是一个简单的容器元素。在这种情况下,我们使用了一个<div>元素,但是其他块级元素,比如<p>,也可以使用。小部件会在初始化时向指定的容器元素添加一个表示进度条值的嵌套<div>元素。

此小部件与其他一些小部件(如手风琴)一样,会自然填满其容器的宽度。其他也以类似方式工作的小部件包括标签页、手风琴、滑块和菜单——每个都需要某种形式的容器来限制其在屏幕上的大小。组件会给容器和内部<div>元素分别添加一系列属性和类名。类名从正在使用的theme文件中获取样式,并且组件完全支持 ThemeRoller。支持 ThemeRoller 意味着你选择的主题可以轻松地更改为另一个 jQuery ThemeRoller 主题,并且小部件将继续正常工作,无需对样式进行任何更改。

添加到小部件的其他属性符合 ARIA 规范,使小部件对使用辅助技术的访问者完全可访问。ARIAAccessible Rich Internet Applications)定义了使 Web 内容对使用辅助技术(如屏幕阅读器)的人更具可访问性的方法。所有 jQuery 小部件都对 ARIA 有不同程度的支持,包括进度条;这是通过在代码中出现其他标签来提供的,例如以下代码中突出显示的标签:

<div id="myProgressbar" class="ui-progressbar ui-widget ui-widget-content ui-corner-all" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="20">

这些帮助将代码转换为辅助技术将理解的内容;没有它们,代码实际上是隐藏的,这会影响最终用户将看到或听到的内容。

列出进度条的选项

写作时,进度条有三个配置选项:

选项 默认值 用法
disabled false 禁用小部件
Max 100 进度条的最大值
Value 0 设置小部件的值(以百分比表示)

设置进度条的值

更改progressbar1.html中的最终<script>元素,使其显示如下:

<script>
  $(document).ready(function($){
     $("#myProgressbar").progressbar({
       value: 50
    });
  });
</script>

将此文件保存为progressbar2.htmlvalue选项接受一个整数,并将小部件的内部<div>的宽度设置为相应的百分比。此更改将使小部件显示为本章第一个屏幕截图中的样子,进度条填充了一半。

进度条的事件 API

进度条公开了三个自定义事件,如下表所示:

事件 当...时触发
create 初始化小部件
change 小部件的值更改
complete 小部件的值达到 100%

与其他小部件一样,我们可以在配置对象中以匿名回调函数的形式提供这些事件的值,组件将自动为我们调用该函数,每次事件发生时。

要在progressbar2.html页面中看到此事件的实际效果,请添加以下<button>

<p><button id="increase">Increase by 10%</button>

接下来,将最终的<script>块更改为以下内容:

<script>
  $(document).ready(function($){
    var progress = $("#myProgressbar"),
      progressOpts = {
        change: function() {
          var val = $(this).progressbar("option", "value");
          if (!$("#value").length) {
          $("<span />", { text: val + "%", id: "value"}).appendTo(progress);
      } else {
        $("#value").text(val + "%");
      }
    }
  };
    progress.progressbar(progressOpts);
    $("#increase").click(function() {
      var currentVal = progress.progressbar("option", "value"),
    newVal = currentVal + 10;
    progress.progressbar("option", "value", newVal);
    });
  });
</script>

将此文件保存为progressbar3.html。我们还需要为我们的进度条添加一些样式,因此请添加以下内容到一个新文件,并将其保存为progressIncrease.css

#value { margin-top: -28px; margin-right: 10px; float: right; }

不要忘记从页面的<head>中添加链接到新样式表(在标准 jQuery UI 样式表之后):

<link rel="stylesheet" href="css/progressIncrease.css">

在我们的示例中,我们首先缓存了进度条的选择器,然后为change事件定义了一个事件处理程序。在这个回调函数中,我们首先获取进度条的当前值,这个值将对应于其上次更新后的值。当在事件处理程序内部时,我们可以使用$(this)选择进度条。

假设值小于或等于 100(百分比),我们检查页面上是否已经存在具有idvalue的元素。如果元素不存在(即其值没有长度),我们创建一个新的<span>元素,并将其文本设置为当前值。我们还给它一个id属性并将其定位,以便它出现在进度条内。如果元素已经存在,我们只需将其文本更新为新值。

提示

使用自关闭快捷标签选择器

您可能已经在代码中看到了$("<span />")的使用;这是 jQuery 用于生成标签的完整版本的快捷方式;在这种情况下,它会将其传递的任何内容封装在<span></span>标签中。

我们还为页面上添加的按钮添加了点击处理程序。每当按钮被点击时,我们首先使用getter模式中的option方法获取进度条的当前值。然后,在将值增加10之后,我们使用setter模式中的option方法将内部<div>的值增加10个百分点。将该值添加到<span>元素中以指示进度。

点击按钮的结果如下所示:

进度条事件 API

在本例中,每当增加 10%按钮被点击时,我们都手动设置进度条的值;我们使用标准的option方法,该方法适用于所有 UI 库组件,以检索有关进度条当前状态的信息。

不要忘记,像其他库组件一样,此事件也可以通过在事件名称上添加小部件名称前缀来使用 jQuery 的on()方法,例如,progressbarchange

使用进度条方法

除了所有库组件都公开的常见 API 方法(如destroydisableenablewidgetoption)之外,滑块 API 还公开了value方法,该方法是使用option方法设置进度条值的快捷方式。

我们可以完全像上一个示例中所做的那样,但代码更少,使用value方法。更改progressbar3.html中的最后一个<script>元素,使其如下所示:

<script>
  $(document).ready(function($){
    var progress = $("#myProgressbar");
 progress.progressbar();
    $("#increase").click(function() {
      var currentVal = progress.progressbar("option", "value"), newVal = currentVal + 10;
 progress.progressbar("value", newVal);
 if (!$("#value").length) {
 $("<span />", { text: newVal + "%", id: "value" 
 }).appendTo(progress);
 } else {
 $("#value").text(newVal + "%");
 }
    });
  });
</script>

将此文件保存为progressbar4.html。在这个例子中,我们丢失了配置对象,因为它不是必需的。

使用value方法增加值的逻辑已经移到了<button>元素的点击处理程序中。在事件处理程序中,我们获取currentVal的值,然后加上10,并将其赋值给newVal。进度条小部件的value属性被更新为新值;进行检查以查看百分比计数文本是否存在。如果不存在(即#value的长度为零),则我们添加一个新的实例,其中包含更新后的数字,并在屏幕上显示此数字。

但随着更新代码移动到事件处理程序中,我们看到这使我们能够以更简洁的格式执行与上一个示例相同的操作。

添加不定支持

到目前为止,我们已经看到了在更新其结果时如何控制进度条应该使用的百分比值。但是,在某些情况下可能无法始终这样做 - 为了解决这个问题,可以使用一个不定选项。在 jQuery UI 1.10 中添加了这个选项,它允许在不能更新值的情况下使用。这是一个示例,如下图所示:

让我们看一些例子来比较设置已知值和不确定值之间的差异。在progressbar4.html中,将<script>元素更改为以下代码:

<script>
  $(document).ready(function($){
 $("#myprogressbar").progressbar({ value: false });
 $("button").on("click", function(event) {
 var target = $(event.target), progressbar = $("#myprogressbar"), progressbarValue = progressbar.find(".ui-progressbar-value");
 if (target.is("#numButton")) { 
 progressbar.progressbar("option", { value: Math.floor(Math.random() * 100) });
 } else if (target.is("#falseButton")) {
 progressbar.progressbar("option", "value", false);
 }
 });
});
</script>

在代码的<body>元素中,将 HTML 更改为以下代码:

<div id="myprogressbar"></div>
<p>
<button id="numButton">Random Value - Determinate</button>
<button id="falseButton">Indeterminate</button>

将此文件另存为progressbar5.html。点击不定按钮的结果如下截图所示:

添加不定支持

虽然在纸质版本中很难看到它的实际效果,但上一个例子显示了一个持续移动的进度条达到 100%,点击不定按钮会将value属性设置为false,告诉进度条假定值为 100%。在这种情况下,自动设置为 100%,表示我们正在取得进展。由于我们无法准确地得出在每个点上取得了多少进展,进度条小部件会自动假定该值为 100%。

相比之下,如果我们知道进度条应该使用的值,我们可以设置该值。点击随机值 - 确定按钮,在本章的示例中以类似的方式显示设置这样一个值的效果,如下截图所示:

添加不定支持

响应用户交互

在其最基本的层面上,我们可以在响应用户交互时手动更新进度条。例如,我们可以指定一种向导式表单,其中有几个步骤要完成。在这个示例中,我们将创建一个如下截图所示的表单:

响应用户交互

在每个步骤期间,我们可以手动递增进度条,以让用户知道他们进行到了多远的进程。在 progressbar5.html 中,用以下代码替换进度条容器和按钮:

<div class="form-container ui-helper-clearfix ui-corner-all">
  <h1>Registration Form</h1>
  <p>Progress:</p>
  <div id="myProgressbar"></div>
  <label id="amount">0%</label>
  <form action="serverScript.php">>
    <div class="form-panel">
      <h2>Personal Details</h2>
      <fieldset class="ui-corner-all">
        <label for="name">Name:</label>
        <input id="name" type="text">
        <label for="dob">D.O.B:</label>
        <input id="dob" type="text">
        <label for="passwrd1">Choose password:</label>
        <input id="passwrd1" type="password">
        <label for="passwrd2">Confirm password:</label>
        <input id="passwrd2" type="password">
      </fieldset>
    </div>
    <div class="form-panel ui-helper-hidden">
      <h2>Contact Details</h2>
      <fieldset class="ui-corner-all">
        <label for="email">Email:</label>
        <input id="email" type="text">
        <label for="tel">Telephone:</label>
        <input id="tel" type="text">
        <label for="address">Address:</label>
        <textarea id="address" rows="3" cols="25"></textarea>
    </fieldset>
  </div>
  <div class="form-panel ui-helper-hidden">
    <h2>Registration Complete</h2>
    <fieldset class="ui-corner-all">
      <p>Thanks for registering!</p>
    </fieldset>
  </div>
  </form>	
  <button id="next">Next</button>
  <button id="back" disabled="disabled">Back</button>
</div>

将此文件保存为 progressbar6.html。在 <head> 部分,我们添加了一个链接到框架主题文件,就像我们在本章的其他示例中所做的那样,并且将需要添加一个链接到稍后添加的自定义样式表:

<link rel="stylesheet" href="css/progressTheme.css">

页面的 <body> 元素包含一些布局元素和一些文本节点,但主要元素是进度条的容器和 <form><form> 部分使用 <div><fieldset> 元素分隔为几个不同的部分。这样做的原因是我们可以隐藏表单的部分,使其看起来好像跨越了几个页面。

我们在进度条旁边添加了一个段落和一个 <label> 参数。我们将对它们进行定位,使它们出现在小部件内部。段落包含一个简单的文本字符串。标签将用于显示当前进度值。

外部容器被赋予几个类名;第一个是我们可以对元素应用一些自定义样式,但下一个两个是为了针对 jQuery UI CSS 框架的不同特性。ui-helper-clearfix 类用于自动清除浮动元素,并且是减少 <div> 元素的额外和不必要的清除混乱的好方法。在创建自己的小部件时,请不要忘记显式使用此类和其他框架类。

提示

我们在第二章中介绍了一些核心 CSS 类;CSS 框架 API 的更多详细信息可在learn.jquery.com/jquery-ui/theming/api/上找到。

ui-corner-all 类用于给容器元素(以及进度条本身,它们自动具有这些特性,以及我们的 <fieldset> 元素)添加圆角,使用了几个专有的样式规则。这些现在被大多数现代浏览器支持。我们还有一个下一个按钮来在每个面板之间前进,并且一个默认情况下被禁用的返回按钮。

我们在表单中使用 CSS 框架的另一个类。页面首次加载时需要隐藏多个面板;因此,我们可以使用 ui-helper-hidden 类来确保它们设置为 display: none。当我们想要显示它们时,我们只需删除此类名。

现在让我们添加 JavaScript。更改页面底部的最后一个 <script> 元素,使其显示如下:

$(document).ready(function($){
  var prog = $("#myProgressbar"), progressOpts = {
    change: function() {
      prog.next().text(prog.progressbar("value") + "%");
    }
  };
  prog.progressbar(progressOpts);
  $("#next, #back").click(function() {
    $("button").attr("disabled", true);
    if (this.id == "next") {
      prog.progressbar("option", "value",
      prog.progressbar("option", "value") + 50);
      $("form").find("div:visible").fadeOut().next()
        .fadeIn(function(){
        $("#back").attr("disabled", false);
        if (!$("form").find("div:last").is(":visible")) {
          $("#next").attr("disabled", false);
        }
      });
    } else {
      prog.progressbar("option", "value", prog.progressbar("option", "value") - 50);
      $("form").find("div:visible").not(".buttons").fadeOut() .prev().fadeIn(function() {
        $("#next").attr("disabled", false);
        if (!$("form").find("div:first").is(":visible")) {
          $("#back").attr("disabled", false);
        }
      });
    }
  });
});

我们首先缓存进度条的选择器,并定义我们的配置对象,利用change事件来指定一个匿名回调函数。每次事件被触发时,我们将使用value方法获取进度条的当前值,并将其设置为直接在进度条元素之后的<label>参数的文本。事件在更改发生后触发,因此我们获得的值将始终是新值。

一旦进度条被初始化,我们为表单后的按钮添加一个点击处理程序。在此处理程序函数内,我们首先禁用两个按钮,以防止重复点击<button>导致表单破坏。然后,我们使用if语句运行稍微不同的代码分支,具体取决于所点击的按钮。

如果点击了下一步按钮,则通过将value选项设置为当前值加上50%来将进度条的值增加50%。然后,我们淡出当前可见的面板,并淡入下一个面板。我们使用回调函数作为fadeIn()方法的参数,该函数将在动画结束时执行。

在此功能内,我们重新启用返回按钮(因为点击了下一步,所以第一个面板不可见,因此应该启用此按钮),并确定是否启用下一步按钮,只要最后一个面板不可见,就可以完成此操作。

外部if语句的第二个分支处理了点击返回按钮的情况。在这种情况下,我们将进度条减少50%,启用下一步按钮,并检查是否应启用返回按钮。

这现在是我们所需的所有 JavaScript 代码。现在我们所要做的就是添加一些基本的 CSS 来布置示例;在文本编辑器中的新文件中添加以下代码:

h1, h2 { font-family: Tahoma; font-size: 140%; margin-top: 0;}
h2 { margin: 20px 0 10px; font-size: 100%; text-align: left; }
p { margin: 0; font-size: 95%; position: absolute; left: 30px; top: 60px; font-weight: bold; }
#amount { position: absolute; right: 30px; top: 60px; font-	size: 80%; font-weight: bold; }
#thanks { text-align: center; }
#thanks p { margin-top: 48px; font-size: 160%; position: relative; left: 0; top: 0; }
form { height: 265px; position: relative; }
.form-container { width: 400px; margin: 0 auto; position: relative; font-family: Verdana; font-size: 80%; padding: 20px; background-color: #C5DBEC; border: 1px solid #2E6E9E; }
.form-panel { width: 400px; height: 241px; position: absolute; top: 0; left: 0; } 
fieldset { width: 397px; height: 170px; margin: 0 auto; 	padding: 22px 0 0; border: 1px solid #abadac; background-color: #ffffff; }
label { width: 146px; display: block; float: left; text-align: right; padding-top: 2px; margin-right: 10px; }input, textarea { float: left; width: 200px; margin-bottom: 13px; }
button { float: right; }

将此保存为 progressTheme.csscss 目录中。现在,我们应该有一个带有已连接的进度条的工作页面。当我们运行页面时,我们应该发现我们可以浏览表单的每个面板,并且进度条将相应地更新自身。

我们仍然依赖用户交互来设置进度条的值,在这个示例中,这是由访问者通过每个面板进行导航驱动的。

使用带有进度条的丰富上传

不再依赖用户交互来增加进度条的值,从而完成指定的任务,我们可以依赖系统来更新它,只要有可用的东西可以准确地更新它。

在我们最终的进度条示例中,我们可以整合 HTML5 文件 API,以便异步上传文件,并可以使用onprogress事件来在文件上传时更新进度条。

提示

此时,您可能想获取伴随本书的代码下载副本,以便您可以在学习示例的同时查看代码。

这个示例只有在安装了并配置了 PHP 的完整 Web 服务器时才能正常工作。在这个示例中,我们不会查看上传过程的服务器端部分;我们只对一旦上传完成,根据从系统收到的反馈来更新进度条感兴趣。

修改progressbar6.html中的<body>,使其包含以下元素:

<div id="container">
  <h1>HTML5 File Reader API</h1>
  <form id="upload" action="upload.php" method="POST" enctype="multipart/form-data">
    <fieldset>
      <legend>Image Upload</legend>
      <input type="hidden" id="MAX_FILE_SIZE" name="MAX_FILE_SIZE"value="300000" />
      <div>
        <label for="fileselect">Image to upload:</label>
        <input type="file" id="fileselect" name="fileselect[]"multiple="multiple" />
      </div>
      <div id="progress"></div>
    </fieldset>
  </form>
  <div id="messages"></div>
</div>

在页面上,我们有一个file类型的<input>元素,后面跟着进度条的容器,就像往常一样。接下来,让我们添加脚本;将<head>末尾的最后一个<script>元素更改为以下代码:

$("document").ready(function($) {
  if (window.File && window.FileList && window.FileReader) {
    $("#fileselect").on("change", function(e) {
      var files = e.target.files || e.dataTransfer.files;
      for (var i = 0, f; f = files[i]; i++) {
        ParseFile(f);
        UploadFile(f);
      }
    });
  }
});

将此文件保存为progressbar7.html。将以下代码添加到一个新文档中,并保存为uploads.js

function ParseFile(file) {
  $("#messages").html(
    "<p>File information: <strong><br>" +
    "</strong> type: <strong>" + file.type + "<br>" +
    "</strong> size: <strong>" + file.size + 
    "</strong> bytes</p>"
  );

  if (file.type.indexOf("image") === 0) {
    var reader = new FileReader();
    reader.onload = function(e) {
      $("#messages").prepend(
        "<br>Image:<br><strong>" + file.name + "</strong><br />" +
        '<img class="preview" src="img/' + e.target.result + '" /></p>'
      );
    };
    reader.readAsDataURL(file);
  }
}

function UploadFile(file) {
  $("#progress").progressbar();
  var xhr = new XMLHttpRequest();
  xhr.upload.onprogress = function updateProgress(e) {
    var fileloaded = (e.loaded / e.total);
    $("#progress").progressbar("value", Math.round(fileloaded * 100));
  };

  xhr.upload.onload = function() {
    $("#progress").progressbar("value", 100);
  };

  xhr.open("POST", $("#upload").action, true);
  xhr.setRequestHeader("X_FILENAME", file.name);
  xhr.send(file);
}

最后,在文档的<head>元素下方立即添加以下内容:

<script type="text/javascript" src="img/uploads.js"></script>

首先,在progressbar7.html中,我们进行检查以确认浏览器是否支持 File API;如果可以,我们就会启动一个事件处理程序,该处理程序会在点击fileselect按钮时立即触发。

在更改处理程序中,我们获取所选文件的详细信息并将其保存到数组中;然后,我们调用ParseFile()函数(在uploads.js中)来首先启动输出消息,然后使用FileReader()加载和读取图像的副本,并将图像的副本输出到屏幕。同时,我们显示图像名称的详细信息。

继续到uploads.js,然后我们调用UploadFile函数,这就是真正的魔法发生的地方。我们首先初始化一个进度条的实例,给它一个progress ID,并使用一个<div>元素作为其容器。然后,代码设置了一个XMLHttpRequest()的实例,并打开了一个POST连接以上传文件。在这种情况下,文件实际上只上传到服务器上的一个测试文件夹(或在这种情况下,您的个人电脑上),称为 uploads;在这一点上,您将创建一个上传脚本,该脚本将把文件重定向到远程服务器上的适当位置。

每当XMLHttpRequest参数更新时,它都会触发onprogress事件处理程序来更新进度条;我们计算总文件大小与已上传内容之间的差异,然后将其转换为百分比,并用此百分比来更新进度条。一旦上传完成,我们就会触发onload()事件处理程序,以确保它显示 100% 完成。

对于这个示例,我们还需要一些 CSS;在一个新的文本文件中添加以下代码:

body { font-family: "Segoe UI", Tahoma, Helvetica, Freesans, sans-serif; font-size: 90%; margin: 10px; color: #333; background-color: #fff; }
#container { margin-left: auto; margin-right: auto; width: 430px;  }
#messages { padding: 0 10px; margin: 1em 0; border: 1px solid #999; width: 400px; clear: both; height: 275px; }
#messages p { position: absolute; float: left; margin-left: 275px; width: 150px; }
#progress { margin-top: 3px; width: 390px; left: -2px; }
h1 { font-size: 1.5em; font-weight: normal; }
legend { font-weight: bold; color: #333; }
.preview { height: 60%; width: 60%; float: left; }
fieldset { width: 400px; }

此文件可以保存在css文件夹中,命名为uploads.css。大部分样式只是定位各个元素并设置进度条的宽度。我们也不需要链接到progressTheme.css,因此也可以将其删除。

当我们运行这个文件时,我们应该看到一旦选择了文件,它就会自动开始上传,并且进度条将开始填充。如果在本地进行测试,速度会相当快,所以最好使用相当大的文件进行测试。

以下屏幕截图显示了上传完成后的页面:

使用进度条实现丰富上传

总结

在本章中,我们看了两个界面小部件,它们都可以提供某种形式的视觉反馈,无论是作为操作的结果还是设置特定的值。我们看到了如何快速、简单地将滑块小部件放在页面上,并且它需要最少的底层标记和仅一行代码来初始化。

我们探讨了可以设置的不同选项,以控制滑块的行为以及在初始化后如何配置它,同时提供可以在交互期间的重要时间执行代码的回调。我们还介绍了可以用于以编程方式与滑块进行交互的方法,包括用于设置手柄值的方法,或在初始化后获取和设置配置选项的方法。

我们还查看了具有紧凑 API 的进度条小部件,它在进程进行时提供了必要的访问者反馈。然后我们研究了在初始化之前或小部件正在使用时可以用来配置小部件的各种选项。我们还研究了可用于与进度条小部件一起工作的方法,看看我们如何可以轻松地对进度更改做出反应,或者在小部件完成后做出反应。

我们还看了进度条如何包含对不确定进度指示器的支持,用于在当前进程状态无法精确确定时使用。

在下一章中,我们将看到日期选择器小部件,它拥有库中所有小部件中最大、功能最丰富的 API,并包含完整的国际化支持。

第七章:日期选择器小部件

jQuery UI 日期选择器小部件可能是 jQuery 库中最精细和文档化的小部件。它具有最大的应用程序编程接口API),可能提供了所有小部件中最多的功能。它不仅可以立即使用,而且还可以高度配置和健壮。

简单地说,日期选择器小部件提供了一个界面,让您网站或应用的访问者选择日期。无论何处需要填写日期的表单字段,都可以添加日期选择器小部件。这意味着您的访问者可以使用一个吸引人并且交互性强的小部件,而您可以得到您期望的日期格式。

在本节中,我们将讨论以下主题:

  • 默认日期选择器的实现

  • 探索可配置选项

  • 实现触发按钮

  • 配置替代动画

  • dateFormat选项

  • 简单的本地化

  • 多月日期选择器

  • 数据范围选择

  • 日期选择器小部件的方法

  • 使用 AJAX 与日期选择器

内置到日期选择器中的其他功能包括自动打开和关闭动画以及使用键盘导航小部件界面的能力。在按住Ctrl键(或 Mac 上的命令键)时,键盘上的箭头可以用来选择新的日期单元格,然后可以使用返回键进行选择。

尽管易于创建和配置,但日期选择器是一个由各种底层元素组成的复杂小部件,如下图所示:

日期选择器小部件

注意

尽管存在这种复杂性,但我们可以只用一行代码来实现默认日期选择器,就像我们迄今为止介绍的库中的其他小部件一样简单。

实现日期选择器小部件

要创建默认日期选择器,请在文本编辑器中的新页面中添加以下代码:

<!DOCTYPE html>
<html>
<head>
  <meta charset = "utf-8">
  <title>Datepicker</title>
  <link rel="stylesheet" href="development-bundle/themes/redmond/jquery.ui.all.css">
  <script src="img/jquery-2.0.3.js"></script>
  <script src="img/jquery.ui.core.js"></script>
  <script src="img/jquery.ui.widget.js"></script>  
<script src="img/jquery.ui.datepicker.js"> </script>
  <script>  
    $(document).ready(function($){
      $("#date").datepicker();
    });
  </script>
</head> 
<body>
  <label for="date">Enter a date:</label>
  <input id="date" />
</body>
</html>

将此保存为jqueryui项目文件夹中的datePicker1.html。我们页面上只有一个<label>和一个标准文本<input>元素。我们不需要为了渲染日期选择器小部件而指定任何空容器元素,因为创建小部件所需的标记会被库自动添加。

提示

尽管在您的<input>语句中使用 HTML5 的type="date"属性可能很诱人,但不建议这样做——这可能会导致冲突,即同时显示 jQuery UI 日期选择器和本机 HTML5 版本。

当您在浏览器中运行页面并聚焦于<input>元素时,默认日期选择器应该出现在输入框下方。除了一个<input>元素外,日期选择器也可以附加到一个<div>元素上。

除了外观漂亮之外,默认日期选择器还带有许多内置功能。当日期选择器打开时,它会平滑地从零到全尺寸进行动画,并且将自动设置为当前日期。选择日期将自动将日期添加到 <input> 并关闭日历(再次使用漂亮的动画)。

如果没有额外的配置并且只有一行代码,我们现在已经拥有了一个完全可用且具有吸引力的小部件,使日期选择变得容易。如果您只想让人们选择一个日期,这就是您所需要的全部。默认日期选择器所需的源文件如下:

  • jquery-2.0.3.js

  • jquery.ui.core.js

  • jquery.ui.widget.js

  • jquery.ui.datepicker.js

使用内联日历选择日期

我们创建了一个基本的日期选择器小部件,将其链接到一个普通的文本 <input> 框中。虽然这样做完全没问题,但有时您可能不想使用普通输入框,而只需在页面中显示已打开的日历。

幸运的是,使用日期选择器小部件很容易实现。更改 HTML 代码以使用 <div> 元素,如下代码所示:

<body>
 Enter a date: <div id="date"></div>
</body>

如果在浏览器中预览结果,您会注意到输入文本框已经消失,并且日历已经完全显示出来:

使用内联日历选择日期

日期选择器的可配置选项

日期选择器具有大量可配置的选项(目前确切为 50 个)。以下表格列出了基本选项、它们的默认值,并简要描述了它们的用法:

选项 默认值 用法
altField "" 指定替代 <input> 字段的 CSS 选择器,其中还添加了所选日期。
altFormat "" 指定要添加到替代 <input> 中的日期的替代格式。有关此选项接受的值的澄清,请参见后面部分中的 dateFormat 选项。
appendText "" 在日期选择器 <input> 后添加文本以显示所选日期的格式。
autoSize false 自动设置 <input> 元素的宽度,以便根据指定的 dateFormat 容纳日期。
beforeShow null 允许日期选择器配置对象在调用之前更新日期选择器。
beforeShowDay null 接受日期作为参数,并返回值以指示该日期是否可选择,要添加到日期单元格的类名,以及日期的(可选)弹出工具提示。该函数在日期选择器中的每一天显示之前调用。
buttonImage "" 指定用于触发 <button> 的图像的路径。
buttonImageOnly false 设置为 true 以使用图像而不是触发按钮。
buttonText "..." 提供要显示在触发 <button> 上的文本(如果存在)。
calculateWeek $.datepicker. iso8601Week 接受一个函数,用于计算指定日期的一年中的周数。
changeMonth false 显示月份更改下拉列表。
changeYear false 显示年份更改下拉列表。
closeText
constrainInput true <input> 元素限制为小部件指定的日期格式。
currentText "今天" 用于当前日期链接的显示文本。必须与 showButtonPanel 属性一起使用才能显示此按钮。
dateFormat 用于解析和显示日期的格式。在本章后面的 更改日期格式 部分显示了完整的格式列表。
dayNames [ "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" ] 用于与 dateFormat 属性结合使用的长日期名称列表。
dayNamesMin [ "日", "一", "二", "三", "四", "五", "六" ] 包含在日期选择器小部件中列标题上显示的最小化日期名称的数组。这可以是本地化的,我们将在本章后面看到。
dayNamesShort [ "周日", "周一", "周二", "周三", "周四", "周五", "周六" ] 用于小部件的 dateFormat 属性的缩写日期名称列表。
defaultDate null 设置日期选择器打开时将突出显示的日期,当 <input> 元素为空时。
duration "normal" 设置日期选择器打开的速度。
firstDay 0 设置一周的第一天,从星期日的 0 开始,到星期六的 6 结束。
gotoCurrent false 将当前日期链接设置为将日期选择器小部件移动到当前选择的日期,而不是今天。
hideIfNoPrevNext false 当不需要时隐藏上一个/下一个链接,而不是禁用它们。
isRTL false 控制所使用的语言是否从右到左绘制。
maxDate null 设置可选择的最大日期。接受日期对象或相对数字。例如:+7,或 +6m 等字符串。
minDate null 设置可选择的最小日期。接受数字、日期对象或字符串。
monthNames 月份名称数组,例如 [ "一月", "二月", "三月"…] 设置用于小部件中 dateFormat 属性的完整月份名称列表。
monthNamesShort 缩写月份名称数组,例如["一月", "二月", "三月"…] 设置日期选择器小部件中每个月头部使用的缩写月份名称列表,由 dateFormat 属性指定。
navigationAsDateFormat false 允许我们使用前一个、下一个和当前链接来指定月份名称。
nextText "下一个" 设置用于下一个月链接的显示文本。
numberOfMonths 1 设置在单个日期选择器小部件上显示的月份数。
onChangeMonthYear Function 当日期选择器移到新的月份或年份时调用。
onClose Function 当日期选择器小部件关闭时调用,无论是否选择了日期。
onSelect Function 在选择日期选择器小部件后调用。
prevText "Prev" 设置上一个月链接的显示文本。
selectOtherMonths false 允许选择在当前月面板上显示的上一个月或下一个月的日期(参见showOtherMonths选项)。
shortYearCutoff "+10" 在使用年份表示时确定当前世纪;小于此数的数字被视为当前世纪。
showAnim "show" 设置日期选择器小部件显示时使用的动画。
showButtonPanel false 显示一个日期选择器小部件的按钮面板,包括关闭和当前链接。
showCurrentAtPos 0 在多月份日期选择器中设置当前月的位置。
showOn "focus" 设置触发显示日期选择器的事件。
showOptions {} 包含控制配置动画的选项的对象文本。
showOtherMonths false 显示前一个月和下一个月的最后一天和第一天。
showWeek false 显示一个显示年周的列。使用calculateWeek选项确定周。
stepMonths 1 使用上一个和下一个链接导航的月份数。
weekHeader "Wk" 设置要显示为年周列标题的文本。
yearRange "-10:+10" 指定年份下拉菜单中的年份范围。

我们将在本章中详细探讨其中一些选项。

使用基本选项

datepicker1.html中的最终<script>元素更改为以下内容:

<script>  
  $(document).ready(function($){
 $("#date").datepicker({
 appendText: "  (mm/dd/yy)",
 defaultDate: "+5",
 showOtherMonths: true
 });
  });
</script>

将此保存为datePicker2.html。下面的屏幕截图显示了在配置了这些选项之后小部件的外观:

使用基本选项

我们在这个示例中使用了许多选项,只因为有这么多的选项可供选择。在日期选择器甚至显示之前的初始页面的外观可以使用appendText选项进行更改。这将使用<span>元素直接在<input>字段后面添加指定的文本字符串,与选择器关联。这有助于访问者澄清将用于日期的格式。

为了样式的目的,我们可以使用.ui-datepicker-append类名来定位新的<span>元素。

defaultDate选项设置了在日期选择器初始打开时突出显示的日期,而<input>元素为空。在这个示例中,我们使用了相对的+5字符串,因此当日期选择器小部件初始打开时,选择了距当前日期五天的日期。按下键盘上的Enter键将选择突出显示的日期。

除了相对字符串,我们还可以将 null 作为 defaultDate 的值来供应,将其设置为当前日期(主观上的今天),或者使用标准的 JavaScript 日期对象。

正如我们在上一个截图中所看到的那样,日期选择器小部件中当前日期的样式与显示默认日期的样式不同。这将因主题而异,但供参考的是,当前日期以粗体显示,并用浅色(橙色)显示,而所选日期具有比正常日期更深的边框与默认主题。

一旦选择了日期,随后再次打开日期选择器小部件时,将显示所选日期作为默认日期,这再次具有不同的样式(在 redmond 主题下,预选日期将为浅蓝色)。

通过将 showOtherMonths 选项设置为 true,我们已经向日期表格的开始和结束的空方块中添加了来自上个月和下个月的灰色(不可选择)日期。这些在上一个截图中可见,并且呈现为比可选择日期要浅得多的颜色。

最小和最大日期

默认情况下,日期选择器将无限制地向前或向后,没有上限或下限。如果我们想要将可选择的日期限制在特定范围内,我们可以轻松地使用 minDatemaxDate 选项来实现。将 datePicker2.html 中的配置对象更改为以下内容:

$("#date").datepicker({
 minDate: new Date(),
 maxDate: "+10"
});

将此保存为 datePicker3.html。在本例中,我们向 minDate 选项提供了一个标准的未修改的 JavaScript 日期对象,这将使过去的任何日期都无法选择。

对于 maxDate 选项,我们使用相对文本字符串 +10,这将使只有当前日期和接下来的 10 个日期可选择。您可以看到这些选项如何影响小部件的外观在以下截图中:

最小和最大日期

注意

minDatemaxDate 选项也可以采用诸如 +6w-10m1y 的字符串,分别代表周、月和年。您可以在 api.jqueryui.com/datepicker/#option-minDateapi.jqueryui.com/datepicker/#option-maxDate 上找到有关如何设置这些选项的更多详细信息。

更改日期选择器界面中的元素

日期选择器 API 公开了许多与在日期选择器中添加或删除额外 UI 元素直接相关的选项。要显示 <select> 元素,让访客选择月份和年份,我们可以使用 changeMonthchangeYear 配置选项:

$("#date").datepicker({
 changeMonth: true,
 changeYear: true
});

将此保存为 datePicker4.html。使用月份和年份的 <select> 元素,为用户提供了一个更快的方式来导航到可能遥远的日期。以下截图显示了启用这两个选项后小部件的外观:

更改日期选择器 UI 中的元素

默认情况下,年份选择框将包括上一个和下一个 10 年,总共涵盖 20 年的范围。我们可以使用前/后箭头链接进一步导航,但如果我们事先知道访问者可能会选择非常久远或未来的日期,我们可以使用yearRange选项更改年份范围:

$("#date").datepicker({
  changeMonth: true,
  changeYear: true,
 yearRange: "-25:+25"
});

将其保存为datePicker5.html。这次运行页面时,我们应该发现年份范围现在总共覆盖了 50 年。

我们还可以对日期选择器的 UI 进行另一个更改,以启用按钮面板,这将在小部件底部添加两个按钮。让我们看看它实际操作时的效果。

更改datepicker5.html中的配置对象,使其如下所示:

$("#date").datepicker({ showButtonPanel: true })

将其保存为datePicker6.html。添加到小部件底部的按钮与对话框小部件中的按钮完全相同,您可以在下图中看到:

更改日期选择器 UI 中的元素

今天按钮将立即将日期选择器导航回显示当前日期的月份,而完成按钮将在不选择日期的情况下关闭小部件。

我们还可以更改今天按钮,使其转到所选日期而不是当前日期,方法是将其添加到小部件的配置对象中,如下所示:

$("#date").datepicker({
  showButtonPanel: true,
 gotoCurrent: true 
});

如果您选择一个日期,然后滚动几个月,您可以通过点击今天按钮返回到所选日期。

添加一个触发按钮

默认情况下,当与其关联的<input>元素接收焦点时,日期选择器会打开。然而,我们可以非常轻松地更改这一点,使得日期选择器在按钮被点击时打开。最基本类型的<button>可以通过showOn选项仅启用。将datePicker6.html中的配置对象更改为以下内容:

$("#date").datepicker({ 
 showOn: "button" 
});

将其保存为datePicker7.html。在我们的配置对象中将showOn选项设置为true将会在关联的<input>元素后自动添加一个简单的<button>元素。我们还可以将此选项设置为both,这样当<input>聚焦时以及当<button>被点击时都会打开。

现在,日期选择器仅在点击<button>时打开,而不是在<input>聚焦时。此选项还接受字符串值"both",当<input>聚焦时和当<button>被点击时打开小部件。新的<button>如下图所示:

添加一个触发按钮

可以通过将新字符串提供为buttonText选项的值来轻松更改<button>上显示的默认文本(一个省略号);将之前的配置对象更改为以下内容:

$("#date").datepicker({
  showOn: "button",
  buttonText: "Open Calendar"
});

将其保存为datePicker8.html。现在,<button>上的文本应该与我们设置的buttonText选项的值匹配:

添加触发按钮

我们可以使用图像而不是文本作为<button>元素的标签。这是使用buttonImage选项配置的:

$("#date").datepicker({
  showOn: "button",
  buttonText: "Open Calendar",
 buttonImage: "img/cal.png"
});

将此保存为datePicker9.htmlbuttonImage选项的值是一个字符串,由我们想要在按钮上使用的图像的路径组成。请注意,在此示例中,我们还设置了buttonText选项。之所以这样做的原因是,buttonText选项的值会自动用作<img>元素的titlealt属性,也就是添加到<button>中。

我们的触发按钮现在应该如下截图所示:

添加触发按钮

提示

在这个例子中,我们故意没有在这一点上为按钮设置样式,而是专注于添加一个标志。但是,您可以使用 jQuery UI 对其进行样式设置,正如我们将在第八章中看到的按钮和自动完成小部件

如果我们不想使用按钮,我们根本不需要使用按钮;我们可以将<button>元素替换为<img>元素。因此,将datePicker9.html中的配置对象更改为以下内容:

$("#date").datepicker({
  showOn: "button",
  buttonImage: "img/date-picker/cal.png",
  buttonText: "Open Calendar",
 buttonImageOnly: true
});

将此保存为datePicker10.html。这应该为您提供一个漂亮的仅图片按钮,如下截图所示:

添加触发按钮

配置替代动画

日期选择器小部件带有一个吸引人的内置打开动画,使小部件看起来从无到完整大小。其灵活的 API 还公开了几个与动画相关的选项。这些是durationshowAnimshowOptions配置选项。

我们可以设置的最简单的动画配置是小部件打开和关闭的速度。要做到这一点,我们所要做的就是更改duration选项的值。此选项需要一个简单的字符串,可以采用字符串值slownormal(默认值)或fast,或者表示以毫秒为单位的持续时间的数字。

datePicker10.html中的配置对象更改为以下内容:

$("#date").datepicker({
 duration: "fast"
});

将此变体保存为datePicker11.html。当我们在浏览器中运行此页面时,应该会发现打开动画明显更快。

除了更改动画的速度之外,我们还可以使用showAnim选项更改动画本身。默认使用的动画是简单的显示动画,但我们可以更改为使用库中包含的任何其他显示/隐藏效果之一(请参阅第十四章,UI 效果)。将前一个示例中的配置对象更改为以下内容:

$("#date").datepicker({
 showAnim: "drop",
 showOptions: {direction: "up"}
});

将其保存为datePicker12.html。我们还需要使用两个新的<script>资源来使用替代效果。 这些是jquery.ui.effect.js和我们希望使用的效果源文件,在本例中为jquery.ui.effect-drop.js。 我们将在第十四章中更详细地讨论这两种效果,但它们对于此示例的工作至关重要。 确保将它们添加到文件中,在日期选择器的源文件之后:

<script src="img/jquery.ui.datepicker.js">
</script>
<script src="img/jquery.ui.effect.js"></script>
<script src="img/jquery.ui.effect-drop.js"></script>

我们简单的配置对象通过showAnim选项配置了下落动画,并使用showOptions设置了效果的direction选项,由于日期选择器的绝对定位,这是必需的。 当您运行此示例时,日期选择器应该会下降到位,而不是打开。 其他效果可以以相同的方式实现。

显示多个月

到目前为止,我们所有的示例都只涵盖了单月日期选择器,一次只显示一个月。 但是,如果我们希望,我们可以很容易地通过一些配置选项来调整显示不同数量的月份。 在datePicker12.html中在配置对象之前删除效果源文件,并更改配置对象,以使其如下所示:

$("#date").datepicker({
  numberOfMonths: 3
});

将其保存为datePicker13.htmlnumberOfMonths选项接受一个整数,表示我们希望在任何时候在部件中显示的月份数。 我们的日期选择器现在应该看起来像这样:

显示多个月

可显示的月份数量没有上限;然而,随着每个额外月份的显示,部件的性能会降低。 在将焦点放在<input>上并显示部件之间还有明显的延迟。

此外,各个月份面板是并排的,由于它们的大小,很快将超出视口,导致出现水平滚动条。 但是,一旦使用滚动条,日期选择器将关闭,使得超出屏幕边界的月份无法使用。 出于这些原因,最好将显示的月份数量保持在最低限度。

还有几个与多月份日期选择器相关的配置选项。 stepMonths选项控制在使用上一个或下一个链接时更改多少个月份。

stepMonths的默认值为1,因此在我们先前的示例中,部件以当前月份显示为开始,接着显示接下来的两个月份。 每次单击上一个下一个图标时,面板向左或向右移动一个空间。

如果我们将stepMonths设置为3,与显示的月份数相同,每次单击上一个或下一个链接时,每个月将向左或向右移动三个空间,因此每次单击时都会显示全新的面板。

showCurrentAtPos 选项指定了在显示日期选择器时当前月份显示的位置。在我们之前的例子中,当前月份显示为第一个月面板。每个月面板都有一个从零开始的索引号,所以如果我们希望当前月份显示在小部件的中间,我们会将此选项设置为 1

以垂直方式显示日期选择器

在前面的示例中,注意到应将使用多个月份的情况保持在最低限度,因为如果日历向右滚动太远,我们无法更改用于宽度的样式。

我们可以通过调整 numberofMonths 选项来在一定程度上缓解这个问题。它接受两个属性:第一个是控制我们显示的月份数量,第二个是要使用的列数。如果我们根据 datepicker13.html 中的示例设置,将其设置为在单列中显示两个月,它可能如下所示:

以垂直方式显示日期选择器

要实现此效果,我们只需更改 datepicker13.html 中的配置对象如下所示:

$("#date").datepicker({
 numberOfMonths: [2, 1]
});

您会发现日期选择器现在仅显示两个日历月份,并且现在以垂直格式显示。然后,我们可以使用一点 jQuery 来获取窗口的大小,并根据返回的大小设置 numberOfMonths 属性:

function responsive(){
  var winWidth = $(window).width();
   if((winWidth < 991)&&(winWidth >= 768)) { 
    // tablet
    $("#date").datepicker("option", "numberOfMonths", [ 2, 1 ]);
  } else {
    //desktop
    $("#date").datepicker("option", "numberOfMonths", 2 );
  }
}

注意

无法手动使用 CSS 实现相同的效果;虽然大多数样式可以更改,但容器宽度是硬编码到库中的,无法更改。

更改日期格式

dateFormat 选项是我们可以使用的高级日期选择器区域设置之一。设置此选项可以让您快速轻松地设置选定日期的格式(显示在 <input> 中)使用各种简写引用。日期格式可以是以下任何字符的组合(它们区分大小写):

  • d: 这是月份中的日期(适用时为单个数字)

  • dd: 这是月份中的日期(两位数字)

  • m: 这是年份中的月份(适用时为单个数字)

  • mm: 这是年份中的月份(两位数字)

  • y: 这是年份(两位数字)

  • yy: 这是年份(四位数字)

  • D: 这是缩写的星期几名称

  • DD: 这是完整的星期几名称

  • M: 这是缩写的月份名称

  • MM: 这是完整的月份名称

  • '...': 这是任何文本字符串

  • @: 这是 UNIX 时间戳(自 1970 年 1 月 1 日起的毫秒数)

我们可以使用这些简写代码快速配置我们喜欢的日期格式,如以下示例所示。将 datePicker13.html 中的配置对象更改为以下内容:

$("#date").datepicker({
 dateFormat:"d MM yy"
});

将新文件保存为 datePicker14.html。我们使用 dateFormat 选项来指定一个包含我们首选日期格式的字符串。我们设置的格式是日期的月份(尽可能使用单个数字)为 d,月份的全名为 MM,四位数的年份为 yy

当选择日期并将其添加到相关的 <input> 中时,它们将按照配置对象中指定的格式,如下面的屏幕截图所示:

更改日期格式

在将字符串用作配置日期的选项值时,我们还可以指定整个文本字符串。但是,如果我们这样做,而字符串中的任何字母都是用作简写的字母,则需要使用单引号对其进行转义。

例如,要将字符串 Selected: 添加到日期的开头,我们需要使用字符串 Selecte'd':,以避免将小写 d 作为月份格式的简写格式:

$("#date").datepicker({
 dateFormat:"Selecte'd': d MM yy"
});

将此更改保存为 datePicker15.html。请注意,我们如何使用单引号将字符串 Selected 中的小写 d 转义起来。现在,当选择日期时,我们的文本字符串将被添加到格式化日期的前缀:

更改日期格式

提示

标签添加样式

您可能希望将 width: 15em 添加为输入框的样式,以便您可以清楚地看到整个文本。我已经将这个添加到了附带本书的下载文件中。

还有一些内置的预配置日期格式,对应于常见的标准或 RFC 注释。这些格式作为常量添加到组件中,并可以通过 $.datepicker 对象访问。例如,让我们根据 ATOM 标准格式化日期:

$("#date").datepicker({
 dateFormat: $.datepicker.ATOM
});

将此保存为 datePicker16.html。在此示例中选择日期时,输入到 <input> 中的值应该是如下屏幕截图所示的格式:

更改日期格式

注意

ATOM 格式或技术上称为 RFC 3339/ISO 8601,是一个国际标准,旨在为日期和时间提供清晰的格式,以避免误解,特别是在数据在使用不同日期格式的国家之间传输时。

预定义日期格式的完整集合列在以下表中:

选项值 简写 格式为…
$.datepicker.ATOM "yy-mm-dd" 2013-07-25
$.datepicker.COOKIE "D, dd M y" 星期三, 25 七月 2013
$.datepicker.ISO_8601 "yy-mm-dd" 2013-07-25
$.datepicker.RFC_822 "D, d M y" 星期三, 25 七月 11
$.datepicker.RFC_850 "DD, dd-M-y" 星期三, 25-七月-11
$.datepicker.RFC_1036 "D, d M y" 星期三, 25 七月 11
$.datepicker.RFC_1123 "D, d M yy" 星期三, 25 七月 2013
$.datepicker.RFC_2822 "D, d M yy" 星期三, 25 七月 2013
$.datepicker.RSS "D, d M y" 星期三, 25 七月 13
$.datepicker.TIMESTAMP @ (UNIX 时间戳) 1302649200000
$.datepicker.W3C "yy-mm-dd" 2013-07-25

更新额外的输入元素

有时我们可能想要使用所选日期更新两个 <input> 元素,也许以显示不同的日期格式。altFieldaltFormat 选项可用于满足此要求。在 datepicker16.html 页面中添加第二个 <input> 元素,其 id 属性为 dateAltDisplay,然后将配置对象更改为以下内容:

$("#date").datepicker({
 altField: "#dateAltDisplay",
 altFormat: $.datepicker.TIMESTAMP
});

将此保存为 datePicker17.htmlaltField 选项接受标准的 jQuery 选择器作为其值,并允许我们选择在主 <input> 更新时更新的额外 <input> 元素。altFormat 选项可以接受与 dateFormat 选项相同的格式。下面的截图显示了使用日期选择器选择日期后页面应该显示的方式:

更新额外的输入元素

更改日期格式

当使用日期选择器部件时,您可能已经注意到通过 getDate 方法(请参阅 日期选择方法 部分)以编程方式返回的日期遵循默认的 GMT 日期和时间标准。为了更改 API 返回的日期格式,应使用 $.datepicker.formatDate() 实用程序方法。让我们看看如何使用此功能。

datePicker17.html 中,将日期配置对象更改如下:

      $("#date").datepicker({
 dateFormat: 'yy-mm-dd',
 onSelect: function(dateText, inst) {
 var d = new Date(dateText);
 var fmt2 = $.datepicker.formatDate("DD, d MM, yy", d);
 $("#selecteddate").html("Selected date: " + fmt2);
 }
      });

将此保存为 datePicker18.html。我们需要添加一个额外的 CSS 样式规则,以便我们可以看到在部件中选择日期的结果。将以下内容添加到我们文件的 <head> 中:

<style type="text/css"> 
  #selecteddate { margin-top: 250px; } 
</style>

如果我们在浏览器中预览结果,您会发现在配置对象中使用 dateFormat 属性设置初始 <input> 字段中使用的日期格式;这被设置为 dd-mm-yy。在 onSelect 事件处理程序中,我们使用 $.datepicker.formatDate 将所选日期更改为以下截图中显示的日期:

更改日期格式

本地化日期选择器部件

除了已列出的选项外,还有一系列本地化选项。它们可用于提供自定义区域设置支持,以便以替代语言显示日期选择器,或更改英语单词的默认值。

针对特定本地化使用的选项列在下表中:

选项 默认值 用途
closeText "关闭" 关闭按钮上显示的文本。
currentText "今天" 当天链接显示的文本。
dateFormat "mm/dd/yy" 当添加到 <input> 中时所选日期应采用的格式。
dayNames ["星期日", "星期一","星期二",``"星期三", "星期四", "星期五","星期六"] 一周中每天的名称数组。
dayNamesMin ["Su", "Mo", "Tu","We", "Th", "Fr", "Sa"] 一周内两个字母的日名称数组。
dayNamesShort ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] 一周内缩写的星期几名称数组。
firstDay 0 指定日期选择器中的第一列天。
isRTL false 将日历格式设置为从右到左。
monthNames ["January", "February",``"March", "April",``"May", "June", "July,``"August", "September",``"October", "November",``"December"] 月份名称数组。
monthNamesShort ["Jan", "Feb", "Mar",``"Apr", "May", "Jun",``"Jul", "Aug", "Sep",``"Oct", "Nov", "Dec"] 月份缩写名称数组。
nextText "Next" 在下一个链接上显示的文本。
prevText "Prev" 显示在上一个链接上的文本。
showMonthAfterYear false 在小部件标题中将月份显示在年份后面。
yearSuffix "" 显示在月份标题中年份后面的附加文本字符串。

已经提供了大量不同的翻译,并存储在development-bundle/ui目录中的i18n文件夹中。每种语言翻译都有自己的源文件,要更改默认语言,我们只需包含替代语言的源文件即可。

datePicker17.html中,在链接到jquery.ui.datepicker.js之后直接添加以下新的<script>元素:

<script src="img/jquery.ui.datepicker-fr.js">
</script>

移除配置对象的altFieldaltFormat属性:

$("#date").datepicker();

将此保存为datePicker19.html,并在浏览器中查看结果:

本地化日期选择器小部件

通过一个新资源的单个链接,我们已经将日期选择器中的所有可见文本更改为另一种语言,而且我们甚至不需要设置任何配置选项。如果我们想要真正国际化日期选择器,甚至有一个包含所有替代语言的汇总文件,我们可以使用它,而不需要包含多个语言文件。

datepicker19.html中,将<head>中的jquery.ui.datepicker-fr.js的链接更改为以下代码:

<script src="img/jquery-ui-i18n.js">
</script>

接下来,将 datepicker 的配置对象更改为以下内容:

$(document).ready(function($){
  $("#date").datepicker();
  $("#date").datepicker("option", $.datepicker.regional["ar"]); 
});

将文件保存为datepicker20.html。如果我们在浏览器中预览结果,您将看到它以阿拉伯语显示小部件。我们使用了日期选择器的选项属性将$.datepicker.regional设置为ar,这是 jQuery UI 对阿拉伯语的代码:

本地化日期选择器小部件

我们将在本章后面的动态本地化日期选择器示例中重新讨论本地化汇总文件。

实施自定义本地化

自定义本地化也非常容易实现。这可以使用包含配置的标准配置对象来完成,这些配置是上表选项的配置值。通过这种方式,可以实现未包含在汇总文件中的任何替代语言。

例如,要实现一个Lolcat日期选择器,删除datePicker20.html的现有配置对象,并添加以下代码:

$("#date").datepicker({
  closeText: "Kthxbai",
  currentText: "Todai",
  nextText: "Fwd",
  prevText: "Bak",
  monthNames: ["January", "February", "March", "April", "Mai", "Jun", "July", "August", "Septembr", "Octobr", "Novembr", "Decembr"],
  monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
  dayNames: ["Sundai", "Mondai", "Tuesdai", "Wednesdai", "Thursdai", "Fridai", "Katurdai"],
  dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Kat"],
  dayNamesMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Ka"],
  dateFormat: 'dd/mm/yy',
  firstDay: 1,
  isRTL: false,
  showButtonPanel: true
});

将此更改保存为datePicker21.html。大多数选项用于提供简单的字符串替换。但是,monthNamesmonthNamesShortdayNamesdayNamesShortdayNamesMin选项需要数组。

请注意,dayNamesMin选项和其他与日期相关的数组应从星期日(或相应的本地化)开始;在这里,我们使用firstDay选项将星期一设置为首先出现的选项。我们的日期选择器现在应该看起来像这样:

实现自定义本地化

注意

对于那些好奇“Lolcat”一词的人,它是一个始于 2006 年的术语,但基于 20 世纪初创作的一系列图像。它用于表示一系列具有(尽管语法不正确或独特)短语的猫图片,旨在制造幽默。您可以在en.wikipedia.org/wiki/Lolcat了解更多关于这种独特幽默形式的信息。

实现回调

最终的配置选项集与小部件公开的事件模型相关。它由一系列回调函数组成,我们可以使用这些函数在与日期选择器的交互期间的不同时间点指定要执行的代码。

这些列在以下表格中列出:

事件 当...时触发
beforeShow 日期选择器即将打开。
beforeShowDay 在日期选择器中呈现每个单独的日期。可用于确定日期是否可选择。
onChangeMonthYear 当前月份或年份发生变化。
onClose 日期选择器已关闭。
onSelect 选择了一个日期。

为了突出这些回调属性有多有用,我们可以将前一个国际化示例扩展为创建一个页面,让访问者可以选择i18n捆绑文件中找到的任何可用语言。

通过捆绑动态本地化日期选择器

本书早期,我们简要介绍了如何使用捆绑文件更改日期选择器显示的语言。这样可以避免引用多个语言文件,从而有助于减少对服务器的 HTTP 请求;不过,缺点是日期选择器小部件将始终以硬编码到小部件属性中的语言显示。

不过我们可以改变这一点。让我们看看如何通过添加语言选择下拉菜单来使用beforeShow回调,以显示选择的语言中的日期选择器。

datePicker21.html中,向页面添加以下新的<select>框,并使用以下<option>元素。出于简洁起见,我仅在此处包含了一部分;您可以在本书附带的代码下载中看到完整的列表:

<select id="language">
<option id="en-GB">English</option>
<option id="ar">Arabic</option>
<option id="ar-DZ">Algerian Arabic</option>
<option id="az">Azerbaijani</option>
<option id="bg">Bulgarian</option>
<option id="bs">Bosnian</option>
<option id="ca">Catalan</option>
<option id="cs">Czech</option>
...
<option id="en-NZ">English/New Zealand</option>
<option id="en-US">English/United States</option>
<option id="eo">Esperanto</option>
<option id="es">Spanish</option>
<option id="et">Estonian</option>
<option id="zh-HK">Chinese</option>
<option id="zh-TW">Taiwanese</option>
</select>

接下来,如下链接到i18n.js捆绑文件:

<script src="img/jquery-ui-i18n.js">
</script>

现在更改最后一个<script>元素,使其如下所示:

<script>  
  $(document).ready(function($){
 $("#date").datepicker({
 beforeShow: function() {
 var lang = $(":selected", $("#language")).attr("id");
 $.datepicker.setDefaults($.datepicker.regional[lang]);
 }
 });
 $.datepicker.setDefaults($.datepicker.regional['']);
  });
</script>

将此文件保存为datePicker22.html。我们使用beforeShow回调来指定每次日期选择器显示在屏幕上时执行的函数。

在该函数内部,我们获取选定的<option>元素的id属性,然后将其传递给$.datepicker.regional选项。使用$.datepicker.setDefaults()实用方法来设置此选项。

当页面首次加载时,<select>元素不会有选定的<option>子元素,由于i18n roll-up 文件的顺序,日期选择器将设置为台湾语。为了将其设置为默认的英语,我们可以在日期选择器初始化后将regional实用程序设置为空字符串。

下图显示了在<select>元素中选择另一种语言之后的日期选择器:

通过 rollup 动态本地化日期选择器

我们可以进一步发展这一点;您可能已经注意到,语言直到点击<input>字段内部显示小部件之前都不会改变。

代码可以运行,但感觉有点笨拙;相反,如果我们改变如何显示小部件,我们就可以消除需要点击<input>字段内部的必要性。我已经在代码下载中包含了如何做到这一点的示例,命名为datepickerXX.html

引入实用方法

在前面例子中,我们使用了日期选择器中可用的实用方法之一,setDefaults用于在所有日期选择器实例上设置配置选项。除此之外,还有几种其他实用方法可供我们使用;这些显示在下表中:

实用 用于...
formatDate date对象转换为指定格式的字符串。使用dateFormat选项时,使用formatDate方法以指定格式返回日期。此方法接受三个参数—转换日期的格式(见选择器的可配置选项中的dateFormat),要转换的date对象以及包含附加设置的可选配置对象。可以提供以下选项:dayNamesShortdayNamesmonthNamesShortmonthNames
iso8601Week 根据 ISO 8601 日期和时间标准返回指定日期所在的周数。该方法接受一个参数—要显示周数的日期。
noWeekends 使周末日期不可选择。可以传递给beforeShowDay事件。
parseDate formatDate的反操作,将格式化的日期字符串转换为日期对象。它还接受三个参数—要解析的日期的预期格式,要解析的日期字符串以及包含以下选项的可选设置对象:shortYearCutoffdayNamesShortdayNamesmonthNamesShortmonthNames
regional 设置日期选择器的语言。
setDefaults 在所有日期选择器上设置配置选项。此方法接受包含新配置选项的对象文字。

所有这些方法都是在$.datepicker管理器对象的单例实例上调用的,该对象在初始化时自动创建并用于与日期选择器的实例进行交互。无论在页面上创建了多少个日期选择器作为 jQuery 对象,它们始终会引用在该页面上创建的日期选择器小部件的第一个实例的属性和方法。

列出日期选择器方法

除了我们可以使用的广泛的配置选项之外,还定义了许多有用的方法,使得与日期选择器一起工作变得轻松自如。

除了在第一章中讨论的共享 API 方法 Introducing jQuery UI,如destroydisableenableoptionwidget之外。日期选择器 API 还公开了以下独特的方法:

方法 用于…
dialog 在对话框小部件中打开日期选择器。
getDate 获取当前选择的日期。
hide 以编程方式关闭日期选择器。
isDisabled 确定日期选择器是否已禁用。
refresh 重绘日期选择器。
setDate 以编程方式选择日期。
show 以编程方式显示日期选择器。

让我们更详细地了解一些这些方法,首先是以编程方式选择日期。

以编程方式选择日期

有时(例如在动态、客户端 - 服务器网站上),我们希望能够在程序逻辑中设置特定日期,而无需访问者以通常的方式使用日期选择器小部件。让我们看一个基本示例。

datePicker22.html中删除<select>元素,并直接在<input>元素之后添加以下<button>

<button id="select">Select +7 Days</button>

现在将最后一个<script>元素更改为如下所示:

<script>  
  $(document).ready(function($){
 $("#date").datepicker();
 $("#select").click(function() {
 $("#date").datepicker("setDate", "+7");
 });
  });
</script>

将其保存为datePicker23.htmlsetDate函数接受一个参数,即要设置的日期。与defaultDate配置选项一样,我们可以提供一个相对字符串(就像在此示例中所做的那样)或一个日期对象。

提示

您可以在api.jqueryui.com/datepicker/#utility-formatDate中查看设置日期对象的一些选项。

如果我们被迫使用字符串作为我们日期选择器的源,我们可以轻松将它们转换为日期对象;为了实现这一点,我们可以使用众多的日期 JavaScript 库,如Moment.js。我在本书的附带代码下载中包含了如何使用此库生成我们的日期对象的简单示例。

在对话框中显示日期选择器

dialog方法产生相同易于使用且有效的日期选择器窗口部件,但它将其显示在一个浮动的对话框中。该方法易于使用,尽管它影响日期选择器对话框的放置;对话框将显示为与日期输入字段分离,我们将会看到。

从页面中删除<button>并将datepicker23.html中的最终<script>元素更改为以下代码:

<script>  
  $(document).ready(function($){
    function updateDate(date) {
      $("#date").val(date);
    }
    $("#date").focus(function() {
      $(this).datepicker("dialog", null, updateDate);
    });
  });
</script>

将此保存为datePicker24.html。首先我们定义一个名为updateDate的函数。当在日期选择器中选择日期时,将自动将所选日期传递给我们页面上的<input>元素。

我们使用focus事件调用dialog方法,该方法接受两个参数。在本例中,我们将第一个参数设为null,因此日期选择器默认为当前日期。

第二个参数是一个在选择日期时执行的回调函数,它映射到我们的updateDate函数。

我们还可以提供额外的第三和第四个参数;第三个是日期选择器的配置对象,第四个用于控制包含日期选择器的对话框的位置。默认情况下,它将在屏幕中央渲染对话框。

提示

您可以在api.jqueryui.com/datepicker/#method-dialog了解更多关于如何配置这些选项的信息。

实现启用 AJAX 的日期选择器

对于我们最终的日期选择器示例,我们将在其中加入一些魔法,并创建一个与远程服务器通信的日期选择器,以查看是否有任何不能选择的日期。然后,这些日期将在日期选择器窗口部件中被标记为不可选择的日期。

更改datepicker24.html<body>,使其包含以下标记:

<div id="bookingForm" class="ui-widget ui-corner-all">
  <div class="ui-widget-header ui-corner-top">
    <h2>Booking Form</h2>
  </div>
  <div class="ui-widget-content ui-corner-bottom">
    <label for "date">Appointment date:</label>
    <input id="date">
  </div>
</div>
<script>  
  $(document).ready(function($){
    var months = [], days = [], x; 
    $.getJSON("http://www.danwellman.co.uk/bookedDates.php?
     jsoncallback=?", function(data) {
      for (x = 0; x < data.dates.length; x++) {
        months.push(data.dates[x].month);
        days.push(data.dates[x].day);
      }
    });

    function disableDates(date) { 
      for (x = 0; x < days.length; x++) {
        if (date.getMonth() == months[x] - 1 && date.getDate() == days[x]) {
          return [false, "preBooked"];
        }
      }
      return [true, ""];
    }

    function noWeekendsOrDates(date) {
      var noWeekend = jQuery.datepicker.noWeekends(date);
      return noWeekend[0] ? disableDates(date) : noWeekend;
    }

    $("#date").datepicker({
      beforeShowDay: noWeekendsOrDates,
      minDate: "+1"
    });
  });
</script>

我们脚本的第一部分最初声明了两个空数组,然后执行一个请求,从一个 PHP 文件获取 JSON 对象。JSON 对象包含一个名为 dates 的选项。该选项的值是一个数组,其中每个项也是一个对象。

每个子对象都包含月份和日期属性,表示应该使其不可选择的一个日期。月份或日期数组由 JSON 对象中的值填充,以供脚本稍后使用。

接下来,我们定义了在beforeShowDay事件上调用的noWeekendsOrDates回调函数。该事件对日期选择器中的 35 个单独日期方块中的每一个都会触发一次。甚至空白的方块也包括在内!

每个日期方块的日期都传递给此函数,该函数必须首先确定所选日期是否不是周末,使用 jQuery UI 的$.datepicker.noWeekends()函数。如果是,则它会自动传递给disableDates函数,否则将被标记为被禁用的。

如果将值传递给disableDates函数,则会将从noWeekendsOrDates函数发送到它的每个方块的日期传递给它,并且必须返回一个包含最多两个项的数组。

第一个是一个布尔值,指示该日期是否可选择,第二个是可选的日期给出的类名。我们的函数循环遍历我们的月份和日期数组中的每个项目,以查看传递给回调函数的任何日期是否与数组中的项目匹配。如果月份和日期项目都与日期匹配,数组将以false和自定义类名作为其项目返回。如果日期不匹配,则返回包含true以指示日期可选择的数组。这使我们能够指定日期选择器中无法选择的任意数量的日期。

最后,我们为日期选择器定义一个配置对象。对象的属性只是用于使 JSON 对象中指定的日期不可选择的回调函数,以及将设置为相对值+1minDate选项,因为我们不希望人们选择过去的日期或当前日期。

除了 HTML 页面之外,我们还需要一些自定义样式。在您的编辑器中的一个新页面中,创建以下样式表:

#date { width: 302px; }
#bookingForm { width: 503px; }
#bookingForm h2 { margin-left: 20px; }
#bookingForm .ui-widget-content { padding: 20px 0; border-top:  none; }
label { margin: 4px 20px 0; font-family: Verdana; font-size: 80%;
float: left; }
.ui-datepicker .preBooked span { color: #ffffff;
background: url(../img/red_horizon.gif) no-repeat; }

将其保存为datepickerTheme.csscss文件夹中。我们使用 PHP 来响应页面发出的请求并提供 JSON 对象。如果您不想在您的 Web 服务器上安装和配置 PHP,您可以使用我在示例中指定的 URL 放置的文件。对于任何有兴趣的人,使用的 PHP 如下所示:

<?php
  header('Content-type: application/json');
  $dates = "({
    'dates':[
      {'month':12,'day':2},
      {'month':12,'day':3},
      etc...
    ] 
  })";
  $response = $_GET["jsoncallback"] . $dates;
  echo $response;
?>

这可以保存为主jqueryui项目文件夹中的bookedDates.php

预订日期只是硬编码到 PHP 文件中。同样,在一个适当的实现中,您可能需要一种更健壮的方式来存储这些日期,比如在数据库中。

当我们在浏览器中运行页面并打开日期选择器时,PHP 文件指定的日期应该根据我们的preBooked类进行样式设置,并且还应完全不响应,如下面的截图所示:

实现 AJAX 启用的日期选择器

摘要

在本章中,我们看了一下由 jQuery UI 库中最大的 API 之一支持的日期选择器小部件。这为我们提供了大量可供使用的选项和从中接收数据的方法。我们首先看了默认实现以及小部件自动添加了多少行为。

我们看了日期选择器暴露的丰富 API,其中包括比任何其他组件更多的可配置选项。我们还看到了如何使用日期选择器管理器对象特有的实用函数。

我们看到了小部件是如何轻松实现国际化的。我们还看到,小部件已经被翻译成了其他34 种语言。每种语言都被打包成一个模块,可以与日期选择器轻松配合使用,以添加对其他语言的支持。我们还看到了如何创建自定义的语言配置。

我们介绍了在日期选择器交互过程中触发的一些事件,并查看了在代码中可用于处理和控制日期选择器的一系列方法。

在下一章中,我们将看到该库中两个较新的添加,即按钮小部件和自动完成小部件。

第八章:按钮和自动完成小部件

按钮和自动完成小部件是库中较新的添加项之一,并随版本 1.8 发布。

传统上,在所有浏览器和平台上一致地为表单元素设置样式是棘手的,并且使情况更加复杂的是,大多数浏览器和平台都以独特的方式呈现表单控件。本章介绍的这两个小部件用于改进 Web 上使用的一些传统表单元素。

按钮小部件允许我们从元素创建外观引人注目且高度可配置的按钮,包括<button><input><a>元素,可以使用 ThemeRoller 生成的主题进行样式设置。支持的<input>元素类型包括submitradiocheckbox。还可以使用附加功能,如图标、按钮集和分割按钮来进一步增强底层控件。

自动完成小部件附加到标准文本<input>上,并用于提供上下文选择菜单。当访客开始在<input>元素中输入时,将显示与输入控件中输入的字符匹配的建议。

通过键盘输入,自动完成可以完全访问,允许使用箭头键导航建议列表,使用Enter键进行选择,并使用Esc键关闭菜单。当使用箭头键导航建议列表时,每个建议都将添加到<input>元素中,然后才能进行选择。如果在导航列表后使用Esc键关闭菜单,则<input>元素的值将恢复为访客输入的文本。

在本章中,我们将介绍以下主题:

  • 标准按钮实现

  • 可配置选项

  • 添加图标

  • 按钮事件

  • 按钮集

  • 按钮方法

  • 使用自动完成与本地数据源

  • 自动完成的可配置选项

  • 自动完成事件

  • 自动完成的独特方法

  • 使用远程数据源与自动完成

  • 在自动完成建议菜单中使用 HTML

介绍按钮小部件

按钮小部件用于为一系列元素和输入类型提供一致的、完全主题化的样式。小部件可以从几种不同的元素创建,并且所得到的小部件的 DOM 以及可用的特性将根据使用的元素略有不同。

一个标准的按钮小部件,可以通过<button><a><input>元素构建,其类型为buttonsubmitreset,将显示如下:

介绍按钮小部件

实现标准按钮

由于按钮可以从几种不同的元素构建,因此我们可以使用一些微小的底层代码变化。 当使用

posted @ 2024-05-19 20:12  绝不原创的飞龙  阅读(37)  评论(0编辑  收藏  举报