10.4.4 工具提示教程

创建一个基本的工具提示真的很容易。本教程将带领你经历这个过程。你可以使用任意自己喜欢的HTML编辑器。

注意:参见本书1.3节了解有关如何下载教程文件的信息。

1.在文本编辑器中打开chapter10目录下的tooltip.html文件。

这个页面已经有一个内部的样式表,它带有一些用来格式化工具提示和触发器的样式,它们和10.4.2节所介绍的样式相同。然而,该页面没有任何工具提示,因此,我们添加一些代码来完成接下来的任务。

2.在靠近文件底部的地方找到结束的</body>标签,并且为一个工具提示添加如下的HTML:


<div class="tooltip"id="tip1">

<h2>A Tooltip</h2>

<p>This is the tooltip text.It's inside a div tag

so you can put anything inside one of these.</p>

</div>


最重要的部分是外围的<div>标签。它包含了class tooltip,这对于CSS以及我们稍后将要加入的程序来说,都是必需的。此外,一个唯一的ID标识出这个特殊的工具提示,并且允许我们将随后将要添加的触发器和这个工具提示连接起来。div中的内容可能是任何的HTML,在这个例子中,是一个标题栏和一个段落。

3.在文件中间的位置,<h1>Tooltips</h1>标题的下面,找到<p>标签。将该段落中的几个单词放入一个<span>标签中,如下所示:


<span class="trigger"data-tooltip="#tip1">accusamus et iusto</span>


这个类表示这个特殊的span是一个工具提示的触发器,该页面中的一些CSS以一种特殊的方式格式化了带有trigger类的任何标签。此外,data-tooltip属性标识出了这个触发器所属的工具提示HTML。现在,我们将添加另一个工具提示。

4.在步骤2中添加的<div>的后面(但是,在结束</body>标签的前面)添加:


<div class="tooltip"id="tip2">

<h2>Another Tooltip</h2>

<p><img src="../_images/small/yellow_h.jpg"

alt="yellow"width="70"height="70"class="imgRight">

This is another tooltip.Look there's even a photo here.</p>

</div>


刚刚添加了另一个工具提示。注意,它和前面的工具提示共享同样的class,但是,它拥有自己唯一的ID:tip2。这个工具提示也包含了一幅图像。现在,我们将为这个工具提示添加触发器。

5.在文件某处的一个段落中,找到另外几个单词,并且将其包含在一个span标签中,如下所示:


<span class="trigger"data-tooltip="#tip2">At vero eos</span>


确保为新的工具提示使用#tip2这个ID。你可以继续添加更多的工具提示和触发器,只要确保为每个工具提示使用相同的ID,并且在为触发器设置data-tooltip属性的时候使用相同的ID。

现在要进行一些编程了。页面已经添加了jQuery文件,并且$(document).ready()函数也已经准备好了。第一个步骤是在页面载入的时候隐藏所有的工具提示。

6.单击$(document).ready()中的空白行,并且输入:


$('.tooltip').hide();


这一行代码相当简单。jQuery的hide()函数(参见6.1.1节)直接隐藏了所有的工具提示,以使得页面载入的时候访问者不会看到它们。当然,当访问者的鼠标光标移动到一个触发器上的时候,你想要单个的工具提示出现,因此,下一个步骤是选择所有的触发器并且添加一个mouseover事件处理程序。

7.在第6行中添加的代码之后输入:


$('.trigger').mouseover(function(){

});//end mouseover


这是一个基本的事件处理程序,就像5.2节所介绍的那些。在这个例子中,选中了所有带trigger类的元素,并且给它们分配了一个mouseover事件。这个函数是工具提示编程的核心,因为它控制了屏幕上的工具提示的显示和放置。识别具体在屏幕上的何处放置一个工具提示,这需要一些技巧,并且,你需要很多不同的信息片才能搞清楚。因此,这个函数的第一部分是创建一系列的变量。

8.在刚才添加的匿名函数中输入如下粗体所示代码:


1$('.trigger').mouseover(function(){

2 var ttLeft,

3 ttTop,

4});//end mouseover


首先创建两个变量,ttLeft保存了工具提示的左边位置,ttTop保存顶部位置。这两个变量此时都是空的,因此,还不需要知道它们应该是什么值。

创建变量的这种方式看上去有点奇怪,你可能习惯使用两个var关键字来创建两个变量,如下所示:


var ttLeft;

var ttTop;


这绝对是可以接受的,但是,当你一次创建一批变量的时候,常用的方法是使用一个var关键字,后面跟着一批变量,都用逗号隔开。这减少了录入,不必重复地输入var。第3行末尾的逗号不是一个输入错误,还有更多的变量需要创建。

9.向代码中添加另一个变量(下面的第4行):


1$('.trigger').mouseover(function(){

2 var ttLeft,

3 ttTop,

4$this=$(this),

5});//end mouseover


$(this)引用触发器元素,并且$this=$(this)用来把对触发器元素的一个引用存储到一个变量中。我们在10.1.4节的标签页面板教程的步骤3中做了同样的事情。在这个函数中,将会多次引用该触发器元素,并且如果重复使用$(this),将会迫使浏览器的JavaScript解释器每次都运行jQuery函数,这很浪费计算机的资源和时间。相反,通过将$(this)存储到一个变量中,jQuery函数只需要运行一次就可以获取触发器元素,这使得程序更加高效(参见本书13.1.2节了解将jQuery选择存储到一个变量中的好处)。

接下来选择与这个触发器相关的工具提示。

提示:当把一个jQuery选择存储到一个变量中的时候,常见的做法是,在变量名的前面添加一个$,如下所示:


var$banner=$('#banner');


包含一个美元符号,这不是必须的,var banner=$('#banner')也能工作。然而,美元符号提醒你,变量保存的是一个jQuery选择,而不是像数字或字符串一样的任何旧的值。

10.添加另一个变量(参见第5行):


1$('.trigger').mouseover(function(){

2 var ttLeft,

3 ttTop,

4$this=$(this),

5$tip=$($this.attr('data-tooltip')),

6});//end mouseover


变量$tip保存了工具提示的一个jQuery选择。代码$($this.att r('data-tooltip'))做了很多事情,因此,这里看看如何分解它。$()中的部分,即$this.attr('data-tooltip'),使用jQuery的.attr()函数来获取触发器的'data-tooltip'属性(记住,$this引用该触发器)。换句话说,这段代码接受了当前的触发器元素,查找一个data-tooltip属性,并且获取其值。例如,对于步骤3中添加的触发器,这段代码返回’#tip1’;对于步骤5中的触发器,这段代码将返回’#tip2’。

一旦获取了data-tooltip值,它会传递给jQuery函数,即上面代码中第5行的outer$()。换句话说,这段代码最终是$('#tip1')或$('#tip2')这样的内容。看上去很熟悉吧,这是jQuery选择。一旦上面的第5行运行了,最终将得到名为$tip的一个变量,它包含了针对正确的工具提示的jQuery选择。然后,你可以使用它在屏幕上显示、动画和定位工具提示。

接下来,你需要收集很多的信息,以便在屏幕上放置工具提示。

11.将下面的第6~12行添加到mouseover函数中。


1$('.trigger').mouseover(function(){

2 var ttLeft,

3 ttTop,

4$this=$(this),

5$tip=$($this.attr('data-tooltip')),

6 triggerPos=$this.offset(),

7 triggerH=$this.outerHeight(),

8 triggerW=$this.outerWidth(),

9 tipW=$tip.outerWidth(),

10 tipH=$tip.outerHeight(),

11 screenW=$(window).width(),

12 scrollTop=$(document).scrollTop();

13});//end mouseover


在这里,你将收集到关于不同的元素的位置和大小的很多信息。图10-10可以帮助你认识这些值:它显示了一个比浏览器窗口大的(带边框的部分)Web页面(灰框)。这个页面向上滚动,因此,其一部分会超出视线而位于浏览器窗口上,并且,由于页面比浏览器窗口要长和宽,页面的部分将会扩展到右边缘和下边缘之外。

上面代码的第6行获取了触发器的顶部和左边位置(图10-10中的#1),由于我们将相对于触发器来定位工具提示,因此需要知道这些。

第7行和第8行使用outerHeight()函数(参见10.3.1节)和outerWidth()函数(参见10.3.1节)来获取触发器的height(#2)和width(#3)(包括补白和边框);而第9行和第10行获取工具提示的width(#4)和height(#5)。由于你不想让工具提示出现在窗口之外,因此还需要知道屏幕的宽度(上面代码的第11行,图10-10中的#6),以及访问者是否将页面向下滚动,如果是的话,滚动了多远(第12行,#7)。不要忘了第12行末尾的;,因为这是我们从第2行开始的var语句的结束。

10.4.4 工具提示教程 - 图1

图 10-10 这张图显示了比浏览器窗口(黑色边框)更高和更宽的一个W e b页面(灰框)。访问者查看的页面已经向下滚动过,因此,页面的顶部部分不可见,页面的右边和底部部分也是不可见的。工具提示放置在文档的末尾,因为这是页面载入的时候放置它的位置。直到步骤15运行代码的时候,程序才确定了工具提示需要出现在哪里,随后将其放置在那里

你可能会问为什么需要这些信息。确定触发器出现在页面上的什么位置,然后将工具提示放在其上面,这不是很容易吗?在大多数情况下,你可以这么做,但是,有几种情况下这种方法实现不了。例如,在图10-11中,触发器位于浏览器窗口的右上角;文档的一部分向上扩展,并且到了窗口的左边。如果工具提示直接放置在触发器上,那么,大多数时候,访问者是看不到它的。换句话说,代码需要更加智能一些:它必须搞清楚,将工具提示放置在触发器上是否会导致它出现在浏览器窗口之外。如果是这种情况,那么,程序必须重新放置工具提示。

首先,我们来看看工具提示直接放在触发器上是否会使其位于浏览器窗口顶端的内部。

12.将如下所示第13~17行代码添加到mouseover函数中:


1$('.trigger').mouseover(function(){

2 var ttLeft,

3 ttTop,

4$this=$(this),

5$tip=$($this.attr('data-tooltip')),

6 triggerPos=$this.offset(),

7 triggerH=$this.outerHeight(),

8 triggerW=$this.outerWidth(),

9 tipW=$tip.outerWidth(),

10 tipH=$tip.outerHeight(),

11 screenW=$(window).width(),

12 scrollTop=$(document).scrollTop();

13 if(triggerPos.top-tipH-scrollTop>0){

14 ttTop=triggerPos.top-tipH-10;

15}else{

16 ttTop=triggerPos.top+triggerH+10;

17}

18});//end mouseover


这里有很多事情要做,但是,首先看一下是否想要相对于触发器来放置工具提示的顶端,这样会有帮助。通常,我们将工具提示放置在触发器上10像素的位置,以便它不会覆盖触发器。要确定顶部位置,你首先获取触发器的顶部位置,然后,减去工具提示的高度,然后再减去10像素。例如,假设触发器距离文档顶部150像素,并且工具提示高100像素。要放置工具提示以使其不会覆盖触发器,用触发器150的顶部位置,减去100得到50像素,然后,减去10像素(这给触发器留下了很小的一点空间)。结果,工具提示放置在距离文档顶部40像素的位置。

如果触发器距离文档顶部10像素,而工具提示高100像素,会发生什么情况?如果你直接按照公式来计算,最终得到10-100,即-90像素的一个顶部位置,超过了文档顶部并且无法看到。

这就是在第13行使用的条件的原因:我们将获取触发器的顶端位置,减去工具提示的高度,然后减去访问者已经向下滚动页面的量。然后,进行测试以确保这个值比0大(如果它小于0,工具提示将放置在浏览器窗口顶端之外)。你还需要考虑到滚动,因为工具提示可能刚好放在触发器之上而没有放置在文档顶端之外,但是,如果页面滚动,它仍然会放置到浏览器窗口的视口之上(这是图10-11所描绘的情况)。

如果该条件为真,那么,工具提示的顶端位置ttTop设置为触发器之上(第14行)。然而,如果该条件为假,运行第16行,它将顶端位置设置为触发器底部10像素(我们通过得到触发器的顶端位置triggerPos.right,然后,加上其高度triggerH,就可以计算得出触发器的底端位置)。

接下来计算工具提示的左边位置。

注意:本节中的示例将工具提示放在触发器之上,但是,你不一定必须这么做。你可以自由地修改程序,看看是否可以让工具提示出现在触发器的下边、左边或右边。

10.4.4 工具提示教程 - 图2

图10-11:当动态地定位页面上的一个元素的时候,需要小心。你不知道访问者浏览器窗口可能有多大,也不知道他是否已经滚动了页面。如果你没有考虑这些事情,很容易意外地将一个元素部分地或全部地放到屏幕之外(图中的阴影区域)

13.将如下所示第18行的代码添加到mouseover函数中:


1$('.trigger').mouseover(function(){

2 var ttLeft,

3 ttTop,

4$this=$(this),

5$tip=$($this.attr('data-tooltip')),

6 triggerPos=$this.offset(),

7 triggerH=$this.outerHeight(),

8 triggerW=$this.outerWidth(),

9 tipW=$tip.outerWidth(),

10 tipH=$tip.outerHeight(),

11 screenW=$(window).width(),

12 scrollTop=$(document).scrollTop();

13 if(triggerPos.top-tipH-scrollTop>0){

14 ttTop=triggerPos.top-tipH-10;

15}else{

16 ttTop=triggerPos.top+triggerH+10;

17}

18 var overFlowRight=(triggerPos.left+tipW)-screenW;

19});//end mouseover


计算左边位置比计算右边稍微困难一点。你不仅需要知道工具提示的一部分是否已经放置到了浏览器窗口右边界之外,还要知道在其外多少。例如,假设一个触发器的左边位置是850像素(在图10-11中用A标记),工具提示是250像素宽(B),并且,浏览器窗口宽度是1000像素(C)。如果你定位工具提示的左边界是850像素,它将从850像素标记的地方横跨到1100像素标记位置(A+B)。这意味着,工具提示的右边100像素是看不见的。为了修正这一问题,你需要知道工具提示扩展到浏览器的右边界之外多少,并且,通过将工具提示向左移动同样的量来调整其左边位置。

上面的第18行计算了工具提示扩展到浏览器窗口右边之外的总量(如果有的话)。为了做到这点,首先计算如果工具提示放置在触发器的左边界时候的最左的边界,即triggerPos.left+tipW(在图10-11中就是A+B)。然后,减去屏幕宽度(C)。如果结果是正值,工具提示的某些部分将位于浏览器窗口之外;如果结果是负值,还有足够的屏幕空间,并且能够很好地放置工具提示。

14.在上一步添加的那行代码之下(上面的第18行),添加如下的代码:


if(overFlowRight>0){

ttLeft=triggerPos.left-overFlowRight-10;

}else{

ttLeft=triggerPos.left;

}


实际上,这段代码是说,如果overFlowRight变量保存的数字大于0(这意味着工具提示放不下),那么将工具提示的左边界ttLeft设置为触发器的左边位置减去工具提示可能要超出窗口的量。额外减去10个像素,以防止工具提示碰到了窗口的边界。如果overFlowRight的值小于0,那么工具提示能很好地放置,将其左边位置设置为与触发器的左边位置一致:

ttLeft=triggerPos. left;

这需要很多数学知识!幸运的是,你能搞定。工具提示的顶端位置和左端位置已经计算完毕,因此,现在我们可以让它出现在屏幕上了。终于完成了!

15.添加第24~28行代码以完成mouseover函数。


1$('.trigger').mouseover(function(){

2 var ttLeft,

3 ttTop,

4$this=$(this),

5$tip=$($this.attr('data-tooltip')),

6 triggerPos=$this.offset(),

7 triggerH=$this.outerHeight(),

8 triggerW=$this.outerWidth(),

9 tipW=$tip.outerWidth(),

10 tipH=$tip.outerHeight(),

11 screenW=$(window).width(),

12 scrollTop=$(document).scrollTop();

13 if(triggerPos.top-tipH-scrollTop>0){

14 ttTop=triggerPos.top-tipH-10;

15}else{

16 ttTop=triggerPos.top+triggerH+10;

17}

18 var overFlowRight=(triggerPos.left+tipW)-screenW;

19 if(overFlowRight>0){

20 ttLeft=triggerPos.left-overFlowRight-10;

21}else{

22 ttLeft=triggerPos.left;

23}

24$tip.css({

25 left:ttLeft,

26 top:ttTop,

27 position:'absolute'

28}).fadeIn(200);

29});//end mouseover


现在到了激动人心的时刻。使用jQuery的函数串联功能(参见4.6.4节),首先是对工具提示应用.css()函数(参见4.8.2节),设置其左边位置和右边位置。由于要定位工具提示,其position属性也设置为absolute,然后fadeIn()函数(参见6.1.1节)很快将工具提示淡入视线。幸运的是,当鼠标光标离开触发器的时候,让工具提示消失,这要简单很多。

16.通过添加如下的30~32行代码完成编程,完成后的代码如下所示:


1$('.trigger').mouseover(function(){

2 var ttLeft,

3 ttTop,

4$this=$(this),

5$tip=$($this.attr('data-tooltip')),

6 triggerPos=$this.offset(),

7 triggerH=$this.outerHeight(),

8 triggerW=$this.outerWidth(),

9 tipW=$tip.outerWidth(),

10 tipH=$tip.outerHeight(),

11 screenW=$(window).width(),

12 scrollTop=$(document).scrollTop();

13 if(triggerPos.top-tipH-scrollTop>0){

14 ttTop=triggerPos.top-tipH-10;

15}else{

16 ttTop=triggerPos.top+triggerH+10;

17}

18 var overFlowRight=(triggerPos.left+tipW)-screenW;

19 if(overFlowRight>0){

20 ttLeft=triggerPos.left-overFlowRight-10;

21}else{

22 ttLeft=triggerPos.left;

23}

24$tip.css({

25 left:ttLeft,

26 top:ttTop,

27 position:'absolute'

28}).fadeIn(200);

29});//end mouseover

30$('.trigger').mouseout(function(){

31$('.tooltip').fadeOut(200);

32});//end mouseout


mouseout的内容很简单:只要当鼠标光标从触发器上移开的时候,淡出任何可见的工具提示。就是这样。保存该文件并且在Web浏览器中测试。该文件的一个完整版本complete_tooltip.html位于chapter10教程文件夹下。

插件提示工具提示,更容易的方法

学习如何编写自己的工具提示,这是掌握用jQuery函数来控制元素的大小和位置的很好的方式。但是,如果你试图找到一些额外的功能,例如,外观漂亮的工具提示框,对话气泡效果,使用Ajax下载工具提示内容的功能,或者精确定位工具提示,那么,这里有大量的jQuery插件,它们提供了比我们在本章中创建的简单脚本更多的功能。

·qTip2(http://craigsworks.com/projects/qtip2/)是一款强大的工具提示插件。它不仅可以创建类似本教程的简单的工具提示,还可以创建对话气泡,它可以跟着鼠标光标在屏幕上移动,从服务器下载内容并在工具提示中显示,还有很多其他功能。甚至可以使用它创建一个对话框、下拉式菜单等。它就像是工具提示的“瑞士军刀”。

·jQuery Tools Tooltip(http://flowplayer.org/tools/tooltip/index.html)是另一款不错的工具提示插件。它创建的工具提

示外观漂亮,具有高度的可定制性。当你查看该插件的时候,也查看一下整个jQuery Tools集合(http://flowplayer.org/t ool s/)。它将自己标榜为“T h e Missing UI Library for the Web”(Web少有的UI库),尽管这是有些夸大的宣传,但它确实基本上满足了很多Web设计师的需求。jQuery工具包含了用于标签页、覆盖、表单、幻灯片(类似于10.3.1节介绍的AnythingSlider)以及其他效果的插件。

·jQuery UI Tooltip(http://wiki.jqueryui.com/w/page/12138112/Tooltip)。我们在10.2节已经介绍了jQuery UI,它是Web设计师可用的用户界面小挂件和工具的一个较大的集合。尽管(在编写本书时)jQuery UI团队还没有正式发布一个工具提示插件,但是,这方面的很多实际工作已经完成,并且计划在jQuery UI库的1.9版本中推出来。来自jQuery UI的所有插件都是一流的。