Pro JavaScript Techniques第七章: JavaScript与CSS

  JavaScript和CSS的交互是现代JavaScript程序设计的支柱。事实上对于所有的现代web应用程序来说,至少使用某些形式的动态交互是必须的。那么做过之后,用户可以更快地操作而更少地把时间浪费在等待页面加载上。将动态技术与第六章提出的事件方面的观念相结合,对于实现无缝而强大的用户体验是非常重要的。
  层叠式样式表是用来对易用的、有吸引力的网页进行修饰和布局的事实标准,它在给用户提供最少的困难的同时为开发者提供最多的能力。当你将那一能力与JavaScript相结合时,你将能够构造强健的用户界面,包括动画、窗口部件(widgets),或动态显示等。

访问样式信息

  JavaScript与CSS的结合全部是以表现作为结果的交互。理解什么对你是可用的,对于精确地达到你想要的交互非常重要。
  用来设置和获取元素的CSS属性的主要工具是其style属性。比如说,如果想要取得一个元素的高度,你可以编写如下代码:elem.style.height。如果你想要设置元素的高度为某个特定值,你可以执行如下代码:ele.style.height="100px"。
  当处理DOM元素的CSS属性时,有两个会碰到的问题,它们并不像一般人所期望的那样运作。首先,JavaScript要求你在设置任何空间尺度时指明单位(就像前面设置高度时所做的那样)。同时,任何空间属性也将返回一个代表元素属性的字符串而非数字(如"100px"而非100)。第二,如果一个元素高为100像素,而你试图获取它的当前高度,你期望从style属性里取得那个"100px",情况却未必会如你所愿。这是因为任何样式表文件或内联CSS预设的样式信息并不能可靠地反映到style属性上。
  这一状况将我们引向JavaScript中处理CSS的一个重要函数:获取一个元素真正的当前样式属性的方法,给你一个预期的精确值。存在一组(来源于W3C和IE特有的变种)相当可靠的方法可以用来得到DOM元素的真正的计算后的样式属性。它们能顾及所有相关的样式表、元素特定属性以及JavaScript所作的修改。当需要得到你正操作的元素的精确视图信息时这些方法将会是极其有用的。
  获取元素的计算后样式值时应该考虑到存在于不同的浏览器间的大量的差异。跟在大多数的情形一样,IE有它自己的方法,而其它所有的浏览器都使用W3C定义的方式来实现。
  程序7-1给出了一个用来找出元素的计算后样式属性值的一个函数,7-2则给出了使用此函数的一个示例。

  程序7-1. 用来得到元素的计算后的实际CSS样式值的一个函数

CODE:

//获取一个特定元素(elem)的样式属性(name)
function getStyle( elem, name ) {
    //如果该属性存在于style[]中,则它最近被设置过(且就是当前的)
    if (elem.style[name])
        return elem.style[name];
    //否则,尝试IE的方式
    else if (elem.currentStyle)
        return elem.currentStyle[name];
    //或者W3C的方法,如果存在的话
    else if (document.defaultView && document.defaultView.getComputedStyle) {
        //它使用传统的"text-Align"风格的规则书写方式,而不是"textAlign"
        name = name.replace(/([A-Z])/g,"-$1");
        name = name.toLowerCase();
        //获取style对象并取得属性的值(如果存在的话)
        var s = document.defaultView.getComputedStyle(elem,"");
        return s && s.getPropertyValue(name);
    //否则,就是在使用其它的浏览器
    } else
    return null;
}
程序7-2. 元素的计算后的CSS样式值未必是style对象里可用值的一种情况
CODE:


    
    


    

I should be 100 pixels tall.



  程序7-2说明了怎样得到一个DOM元素的实际的CSS属性值。在这种情形里你得到的是元素的实际的像素高度,即使其高度是通过头部的CSS来设定的。应该注意的是,你的函数将会忽略度量的单位(比如使用的是百分比)。尽管这一解决方案并不是绝对安全的,它的确是一个良好的出发点。
动态的元素

  动态元素的隐含的意思也就是使用JavaScript和CSS维护或创建的非静态的元素。简单的例子是指示你对时事通讯感兴趣的复选框和弹出式的e-mail输入域。
  在最基本的层面上,有三个关键的属性可用来构造动态效果:位置、尺寸、可见性。使用这三个属性你可以在现代浏览器上模拟大多数常见的用户交互效果。

   元素的位置

  操作元素的位置是在页面中开发动态元素的一个重要构成部分。访问和修改CSS位置属性让你有效地模拟许多流行的动画和交互效果(比如拖放)。
  知道CSS的定位系统是怎样工作是操作元素位置的一个重要步骤。在CSS中,元素使用偏移来定位,使用的度量是相对父元素的左上角的偏移量。图7-1是CSS中使用的坐标系统的一个例子。
[attach]37002[/attach]
  图7-1. 使用CSS的网页里坐标系统示例

  页面上的所有元素都有着某种形式的top(垂直坐标)和left(水平坐标)偏移。大体来说,多数元素简单地根据其周围的元素静态定位。依照CSS标准的提议,一个元素可以有几种不同的定位方案。为了正好地理解这一点,我们来看看程序7-3所示的一个简单的网页。
  程序7-3. 演示使用不同的定位方案的一个网页
CODE:





    

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Etiam …p>
    

Phasellus dictum dignissim justo. Duis nec risus id nunc…p>
    

Sed vel leo. Nulla iaculis, tortor non laoreet dictum, turpis diam …



 我们来看看在上面这个简单的HTML页面的情境里,改变第二个段落的定位方式将会产后怎样不同的布局:
   静态定位: 这是元素定位的默认方式;它简单地遵从文档的自然流向。当一个元素静态定位时,top和left属性将不起作用。静态定位的一个例子见图7-2,其中用于定位的css为:position:static;top:0px;left:0px。
[attach]37003[/attach]
  图7-2. 页面正常(static)布局流里的段落

   相对定位: 这一定位方式与静态定位非常相似,因为元素仍然会遵循正常的文档流直到得到其它指示。但是,设置top或left属性将会导致元素相对它的原来的(静态的)位置发生偏移。相对定位的一个例子如图7-3所示,其中的CSS定位为position:relative;top:-50px;left:50px。
[attach]37004[/attach]
  图7-3. 相对定位,元素被移位到了前一个元素上面,而不再遵循正常的文档流

   绝对定位: 将一个元素完全从正常的页面布局流中抓出来。被绝对定位的元素将相对于其第一个非静态定位的父级元素来显示。如果不存在父元素,它将相对于整个文档被定位。绝对定位的一个例子见图7-4,其中用于定位的css为:position:absolute;top:20px;left:0px。
[attach]37005[/attach]
  图7-4. 绝对定位,元素的位置与页面的左上角相关,显示在已经存在的元素之上

   固定定位: 固定定位将一个元素相对于浏览器的窗口定位。设置一个元素的top和left为0相素,将会使得该元素显示在浏览器的左上角(只要用户还在那个页面上),完全忽略浏览器滚动条的任何动作。固定定位的一个例子见图7-5,其中用于定位的css为:position:fixed;top:20px;right:0px。
[attach]37006[/attach]
  图7-5. 固定定位,元素被定位到页面的右上角,尽管浏览器窗口被向下滚动了。

   取得位置
  元素被定位在何处依赖于它的css参数以及与其邻接的内容而不同。访问CSS属性或计算后的实际值都没有提供的一个能力是,获取元素在页面中或者仅在其它元素中的确切位置。
  首先,我们来看如何获取元素在页面中的位置。你拥有几个可支配的元素属性可用来找到这一信息。所有的现代浏览器都支持以下三个属性;当然它们各自是怎么处理的,又是另外一回事了:
   offsetParent: 理论上,这是元素在其中定位的父级元素。但是在实际情况下,offsetParent引用的元素取决于浏览器(比如说,在FireFox中,它引用根节点,而在Opera中,则是直接父元素。
   offsetLeft和offsetTop: 这些参数是元素在其offsetParent上下文中的水平和垂直偏移。在现代浏览器上,它总是精确的。
  现在,问题在于寻求一种可以跨浏览器工作的用来判定方式元素位置的一致的办法。实现这一点的最一致的办法如程序7-4所示:使用offsetParent属性沿着DOM树上行,一路累加偏移值。

  程序7-4. 计算元素相对于文档的x和y坐标的辅助函数
CODE:
//计算元素的X(水平,左)位置
function pageX(elem) {
    //检查我们是否已经到了根元素
    return elem.offsetParent ?
        //如果我们还能往上,则将当前偏移与向上递归的值相加
        elem.offsetLeft + pageX( elem.offsetParent ) :
        //否则,取当前偏移
        elem.offsetLeft;
}
//计算元素的Y(垂直,顶)位置
function pageY(elem) {
    //检查我们是否已经到了根元素
    return elem.offsetParent ?
        //如果我们还能往上,则将当前偏移与向上递归的值相加
        elem.offsetTop + pageY( elem.offsetParent ) :
        //否则,取当前偏移
        elem.offsetTop;
}
  定位问题的另一部分是计算元素在其父元素中的偏移。需要注意的重要的一点是,简单地使用元素的style.left或style.top属性是不够的,因为你可能想要找出没有用Javascript或CSS定义样式的元素的位置。
  使用元素相对于其父元素的位置,你可以向DOM添加额外的相对该父元素定位的元素。比如,这个值用来建造上下文相关的工具提示是非常理想的。
  为了找到元素相对于其父元素的位置,你必须再一次求助于offsetParent属性。因为该属性并不能保证返回特定元素的实际的父元素,你不得不使用你的pageX和pageY函数来找到父元素与子元素之间的位置差异。在程序7-5所示的两个函数中,我试图首先使用offsetParent,如果它是当前元素的实际的父元素;否则,我将继续使用pageX和pageY方法沿DOM上行,以确定它的实际位置。

  程序7-5. 用来确定元素相对于其父元素位置两个函数
CODE:
//查找元素在其父元素中的垂直位置
function parentX(elem) {
    //如果offsetParent就是元素的parent,则提前返回
    return elem.parentNode == elem.offsetParent ?
        elem.offsetLeft :
        //否则,我们需要找出两个元素相对整个页面的位置,计算差值
        pageX( elem ) - pageX( elem.parentNode );
}
//查找元素在其父元素中的垂直位置
function parentY(elem) {
    //如果offsetParent就是元素的parent,则提早返回
    return elem.parentNode == elem.offsetParent ?
        elem.offsetTop :
        //否则,我们需要找出两个元素相对整个页面的位置,计算差值
        pageY( elem ) - pageY( elem.parentNode );
}
定位问题的最后一方面是找出元素相对于其CSS容器的位置。如前面所讨论的,元素可能实际被包含在一个元素中而相对于另一个元素被定位(通过使用相对和绝对定位)。记住这一点,你可以回头利用getStyle函数来得出计算后的CSS偏移值,因为那正是等效的定位。
  有两个可用的简单的包装函数可以处理这一点,如程序7-6所示。它们都只是简单调用getStyle函数,但同时也删除任何多余的(除非你不是使用基于像素的布局,它才是有用的)单位信息(比如说,100px将变成100)。

  程序7-6. 找出元素的CSS定位的辅助函数
//得到元素的left位置
function posX(elem) {
    //取得计算后样式并从中提取数字
    return parseInt( getStyle( elem, "left" ) );
}
//得到元素的top位置
function posY(elem) {
    //取得计算后的样式并从中提取数字
    return parseInt( getStyle( elem, "top" ) );
}
设置元素位置
  不同于取得元素的的位置,设置位置要少许多变数。但是联合使用各种方式的布局(absolut,relative,fixed)时,你将能得到相当的、可用的结果。
  目前,调整元素位置的唯一的办法是通过修改它的CSS属性。为了保持方法上的一致性,你应该仅修改left和top属性,尽管存在着其它的属性(如bottom和top)。作为开端,你可以轻松地创建一对函数,如程序7-7所示,用来设置一个元素的位置,而不考虑其当前位置。

  程序7-7. 不考虑其当前位置,设置元素的x和y位置的一对函数

[Copy to clipboard] [ - ]
CODE:
//设置元素垂直位置的一个函数
function setX(elem, pos) {
    //使用像素为单位,设置CSS属性'left'
    elem.style.left = pos + "px";
}
//设置元素水平位置的一个函数
function setY(elem, pos) {
    //使用像素为单位,设置CSS属性'top'
    elem.style.top = pos + "px";
}

  最终,你需要开发第二套函数,如程序7-8所示,你可以用它们来设置一个元素相对于其原来的位置的位置——比如,调整一个元素使其水平位置比当前值小5个像素。这一方法的使用直接与许多作为DHTML开发的支柱的动画效果相关。

  程序7-8. 用来调整元素相对于基原来的位置的一对函数

[Copy to clipboard] [ - ]
CODE:
//用来把元素的水平位置增加几个像素的一个函数
function addX(elem,pos) {
    //取得当前的水平位置并向其加入偏移
    setX( posX(elem) + pos );
}
//用来把元素的垂直位置增加几个像素的一个函数
function addY(elem,pos) {
    //取得当前的垂直位置并向其加入偏移
    setY( posY(elem) + pos );
}

  现在我已经将处理元素位置的问题完全贯串了一遍。理解元素定位怎样工作和怎么设置及获取元素的精确位置是处理动态元素的一个基本的方面。你将看到的下一个侧面是元素的确切尺寸。

   元素的尺寸

  计算元素的高度和宽度可能是既无比简单又痛苦的一件事,这取决于具体的情况和你需要它做什么。许多情况下,你只需要使用getStyle函数的一个修改版本来得到元素的当前宽度和高度,如程序7-9所示。

  程序7-9. 检索DOM元素的当前高度和宽度的两个函数

[Copy to clipboard] [ - ]
CODE:
//获取元素的实际高度(使用计算后的CSS)
function getHeight( elem ) {
    //取得计算后的CSS值并解析出一个可用的数字
    return parseInt( getStyle( elem, 'height' ) );
}
//获取元素的实际宽度(使用计算后的CSS)
function getWidth( elem ) {
    //取得计算后的CSS值并解析出一个可用的数字
    return parseInt( getStyle( elem, 'width' ) );
}

  当你试图做这两件事的时候麻烦就来了:第一,当你想要得到元素预定义的完整高度(比如说,你将一个动画从0px开始,但你需要知道该元素应该到达多高多宽),第二,当一个元素的display设为"none"时,你将取不到值。
  程序7-10里给出的两个函数说明了怎样找出元素潜在的完整高度和宽度,不论它当前的高度是多少。这是通过访问clientWidth和clientHeight属性实现的,它们提供元素能够展开到的可能的总的区域。

  程序7-10. 用来找出元素的潜在高度和宽度的两个函数,即使元素是隐藏的

[Copy to clipboard] [ - ]
CODE:
//找出元素完整的、可能的高度(不是实际的、当前的高度)
function fullHeight( elem ) {
    //如果元素当前是显示的,那么offsetHeight应该可以成功,即使失败,getHeight也可以生效
    if ( getStyle( elem, 'display' ) != 'none' )
        return elem.offsetHeight || getHeight( elem );
    //否则,我们必须处理display为'none'的元素,
    //这时我们需要重置它的CSS属性以得到更精确的读数
    var old = resetCSS( elem, {
        display: '',
        visibility: 'hidden',
        position: 'absolute'
        });
    //计算元素的完整高度,如果clientHeight无效,则用getHeight()
    var h = elem.clientHeight || getHeight( elem );
    //最后,我来来恢复元素本来的CSS属性
    restoreCSS( elem, old );
    //并返回元素的完整高度
    return h;
}
//找出元素完整的、可能的宽度(不是实际的、当前的宽度)
function fullWidth( elem ) {
    //如果元素当前是显示的,那么offsetWidth应该可以成功,即使失败,getWidth也可以生效
    if ( getStyle( elem, 'display' ) != 'none' )
        return elem.offsetWidth || getWidth( elem );
    //否则,我们必须处理display为'none'的元素,
    //这时我们需要重置它的CSS属性以得到更精确的读数
    var old = resetCSS( elem, {
        display: '',
        visibility: 'hidden',
        position: 'absolute'
    });
    //计算元素的完整宽度,如果clientWidth无效,则用getWidth()
    var w = elem.clientWidth || getWidth( elem );
    //最后,我来来恢复元素本来的CSS属性
    restoreCSS( elem, old );
    //并返回元素的完整宽度
    return w;
}
//用来设置一系列的CSS属性的一个函数,这些属性稍后可以恢复
function resetCSS( elem, prop ) {
    var old = {};
    //遍历每一个属性
    for ( var i in prop ) {
        //记录原来的属性
        old[ i ] = elem.style[ i ];
        //并设置新的值
        elem.style[ i ] = prop[i];
    }
    //返回改变的值的集合,以备restoreCSS使用
    return old;
}
//恢复resetCSS函数引用的副作用的函数
function restoreCSS( elem, prop ) {
    //将所有的属性重新设置为它们原来的值
    for ( var i in prop )
        elem.style[ i ] = prop[ i ];
}

  同时拥有了取得元素当前的和潜在的宽度与高度的能力,你可以使用这些值来开发出一些你能够达到的动画。但是,在我进入动画的细节之前,你还需要看看怎样修改元素的可见性。

   元素的可见性

  元素的可见性是可在JavaScript中用来创建从动画到快速模板效果的每一样东西的强大工具。然而,更重要的是,它也能用来从视图中快速地隐藏元素,提供一些基本的用户界面功能。
  在CSS里有两种不同的方式来有效地从视图中隐藏元素;它们各自有其益处但也能产生无意的后果,这取决于你怎样使用它们:
  ◇ visibility属性决定一个元素是否可见,同时仍保持它在布局流中的正常占位。visibility属性有两个值:visible(缺省值)和hidden(使一个元素完全不可见)。比如说,如果你有一些标签中换行的visibility属性设为hidden的文本,结果将简单地显示为文本中的一个空白块,尺寸与原始文本完全相同。例如,比较以下两行文本:
  //正常文本:
  Hello John, how are you today?
  //对"John"应用了"visibility:hidden"的文本
  Hello     , how are you today?
  ◇ display属性为开发者提供了更多的选项来控制元素的而局。这些选项是inline(类似于的标签是行内的,也就是说他们遵循正常的文本流布局),block(类似于

的标签是块级的,他们打破正常的文本流),和none(从文档中彻底隐藏元素)。将display属性设为none的结果表面上跟你把它从文档中删除完全一致;然而,实情并非那样,因为它可以在迟些时候快速地被切换回视图里。下面的两说明了display属性是怎样工作的:
  //正常文本:
  Hello John, how are you today?
  //对"John"应用了"display:none"的文本
  Hello , how are you today?
  尽管visibility属性有它的特定的用途,display属性的重要性不容忽视。元素的visibility属性被设为hidden时它仍存在于正常的文本流中,这使用得在许多应用中visibility的可行性打了折扣。程序7-11中展示了使用display属性来切换元素可见性的两种方法。

  程序7-11. 使用CSS Display属性来切换元素的可见性的一组函数

[Copy to clipboard] [ - ]
CODE:
//用来(使用display)隐藏元素的一个函数
function hide( elem ) {
    //找到元素的当前显示状态是什么
    var curDisplay = getStyle( elem, 'display' );
    //记录它的显示状态
    if ( curDisplay != 'none' )
        elem.$oldDisplay = curDisplay;
    //将display设为none(隐藏元素)
    elem.style.display = 'none';
}
//用来(使用display)显示元素的函数
function show( elem ) {
    //将display属性设为它曾经的值,或者使用'',如果没有保存过先前的display的话
    elem.style.display = elem.$oldDisplay || '';
}

  可见性的另一面是元素的透明度。调整元素透明度产生的结果与设置元素的visibility非常相似,但是了对元素有多可见的更好的控制。这意味着你可以使一个元素50%可见,使得你可以看到在它下面的元素。所有的现代浏览器都在一定程度上支持透明度,IE和W3C兼容的浏览器再一次在实现方式上有着不同。为了解决这一问题,你可以建创一个标准的函数用来维护元素的透明度,如7-12所示。level为0表示着元素是完全透明的,而level为100表示完全不透明。

  程序7-12. 调整元素的透明度级别的一个函数

[Copy to clipboard] [ - ]
CODE:
//设置元素的透明度级别(level是0-100的数字)
function setOpacity( elem, level ) {
    //如果滤镜存在,这是IE,于是设置Alpha滤镜
    if ( elem.filters )
        elem.style.filter = 'alpha(opacity=' + level + ')';
        //译注:此处原文为ele.style.filters='alpha(opacity=' + level + ')',有误
        //多谢02062007同学的热心验证
    //否则,使用W3C的opacity属性
    else
        elem.style.opacity = level / 100;
}

  掌握了调整元素的位置、大小、及可见性的方法,是时候开始探索你联合使用这些能力做一些有意思的事情了。

[ 本帖最后由 mozart0 于 2007-5-25 15:42 编辑 ]



 附件: 您所在的用户组无法下载或查看附件,您需要注册/登陆后才能查看!
one by one
[广告] 网站博客卖广告推荐:阿里妈妈
mozart0 [楼主]

匪徒田老大
版主


帖子 2326
体力 6628
威望 177
注册 2003-6-18

#4
发表于 2007-5-14 13:14  资料  短消息  加为好友  QQ
动画

  现在你已经掌握了执行基本的DHTML操作的基本技能,我们再来看web应用程序中流行的视觉效果之一:动画。如果使用得宜,动画将能够为用户提供有用的反馈,比如将注意力引向屏幕上的新创建的元素。
  我们将先看两个流行的动画效果,再在研究广泛使用的DHTML库时重访它们。

   滑入

  在第一个动画里将处理一个(display属性为"none"的)隐藏元素,你将通过在一秒之内逐渐增加其高度来渐渐地显示它,以取代粗糙的show()函数。程序7-13所示的函数可以用作show()函数的合适的替代,为用户提供更加平滑的视觉体验。

  程序7-13. 通过一在秒之内递增其高度来慢慢显示隐藏元素的函数

[Copy to clipboard] [ - ]
CODE:
function slideDown( elem ) {
    //从0开始扩张
    elem.style.height = '0px';
    //显示元素(但你看不到它,因为高度为零)
    show( elem );
    //得到元素的完整的潜在高度
    var h = fullHeight( elem );
    //我们将做一个在一秒钟内播放的20"帧"的动画
    for ( var i = 0; i <= 100; i += 5 ) {
    
        //保证我们有一个正确的i的闭包
        (function(){
            var pos = i;
            //设置未来特定时间的定时器
            setTimeout(function(){
                //设置元素的新高度
                elem.style.height = ( pos / 100 ) * h  + "px";
                }, ( pos + 1 ) * 10 );
        })();
    }
}

   淡入

  你们将看到的下一个动画与第一个非常相似,不过用先前所创建的setOpacity()函数代替了修改高度。这一函数(如程序7-14)显示一个隐藏的元素,并将其透明度从0(完全透明)逐渐变化到100%(完全不透明)。与7-13的函数一样,它为用户提供更加平滑的视觉体验。

  程序7-13. 通过一在秒之内递增其透明度来慢慢显示隐藏的元素的函数

[Copy to clipboard] [ - ]
CODE:
function fadeIn( elem ) {
    //透明度从零开始
    setOpacity(elem,0);
    //显示元素(但是你看不到它,因为透明度为零)
    show( elem );
    //我们将做一个在一秒钟内播放的20"帧"的动画
    for ( var i = 0; i <= 100; i += 5 ) {
    
        //保证我们有一个正确的i的闭包
        (function(){
            var pos = i;
            //设置未来特定时间的定时器
            setTimeout(function(){
                //设置元素的新的透明度
                setOpacity(elem,pos);
                }, ( pos + 1 ) * 10 );
        })();
    }
}

[ 本帖最后由 mozart0 于 2007-6-20 08:54 编辑 ]

one by one
mozart0 [楼主]

匪徒田老大
版主


帖子 2326
体力 6628
威望 177
注册 2003-6-18

#5
发表于 2007-5-14 13:14  资料  短消息  加为好友  QQ
浏览器

  除了操作特定的DOM元素以外,懂得怎样修改或追踪浏览器及其部件,将大大提升站点与用户间的交互。与浏览器协同工作最重要的两个方面是判定鼠标的位置和及用户将页面滚动了多少。

   鼠标位置

  获取鼠标位置是为用户提供拖放操作和上下文菜单的基本要求,这两种效果都只能通过JavaScript与CSS的交互来实现。
  你首先需要检测的两个变量是光标相对于整个页面的x和y坐标(如程序7-15所示)。因为当前的鼠标坐标只可能从鼠标事件中取得,你最终需要使用一个普通的鼠标事件来捕获它们,如MouseOver或MouseDown(这方面的更多例子见"拖放"小节)。

  程序7-15. 用来在获取鼠标在整个页面中位置的两个通用函数

[Copy to clipboard] [ - ]
CODE:
//取得鼠标的水平位置
function getX(e) {
    //获取事件对象
    e = e || window.event;
    //先取非IE的位置,不成功则用IE的位置
    return e.pageX || e.clientX + document.body.scrollLeft;
}
//取得鼠标的垂直位置
function getY(e) {
    //获取事件对象
    e = e || window.event;
    //先取非IE的位置,不成功则用IE的位置
    return e.pageY || e.clientY + document.body.scrollTop;
}

  需要知道的第二组与鼠标相关的变量是鼠标光标相对于当前交互的元素的位置。可用于取得这些值的两个函数如程序7-16所示。

程序7-16. 取得鼠标相对于当前元素位置的两个函数

[Copy to clipboard] [ - ]
CODE:
//取得鼠标相对于事件对象里e的目标元素(target)的x坐标
function getElementX( e ) {
    //取合适的元素偏移
    return ( e && e.layerX ) || window.event.offsetX;
}
//取得鼠标相对于事件对象里e的目标元素(target)的x坐标
function getElementY( e ) {
    //取合适的元素偏移
    return ( e && e.layerY ) || window.event.offsetY;
}

  在学习本章的"拖放"这一节里浏览器中元素拖放的实现时,我们将重新回到鼠标交互问题。如需更多的鼠标事件的例子,可参见第六章和附录B。

   视口

  浏览器的视口可认为就是浏览器里被滚动条围住的区域。视口包含几个部件:视口窗口,页面,滚动条。正确计算它们的位置和尺寸,是在有大段内容的情况下(比如自动滚屏的聊天室)开发漂亮的交互效果的需要。
   页面尺寸
  你需要关注的第一组属性是当前页面的宽度和高度。一般来说,大多数的实际的页面都被视口所裁切(通过检查视口尺寸和滚动条位置来判定)。程序7-17所示的两个函数使用了前面提到过的scrollWidth和scrollHeight属性(它们表征了一个部件可能的总的宽度和高度,而不仅仅是当前的可见的那一部分)。

  程序7-17. 判定当前页面的宽和高的两个函数

[Copy to clipboard] [ - ]
CODE:
//返回网页的高度(如果新的内容被加入,这一值可能会改变)
function pageHeight() {
    return document.body.scrollHeight;
}
//返回网页的宽度
function pageWidth() {
    return document.body.scrollWidth;
}

   滚动条位置
  接下来,你们将看到怎样断定浏览器滚动条的位置(或者,在另一个意义上,视口在当前页面上的定位情况)。掌握这些数字(使用7-18所示的函数了得),对于超越浏览器提供的贫乏的滚动、建立自己更好的动态滚动,是必不可少的。

  程序序7-18. 用来判定视口在文档上定位于何处和两个函数

[Copy to clipboard] [ - ]
CODE:
//用来检测浏览器在水平方向滚动了多少的函数
function scrollX() {
    //ie6 strict模式里的快捷方式
    var de = document.documentElement;
    //如果浏览器的pageXOffset可用,则使用之
    return self.pageXOffset ||
    
        //否则,尝试取得根节点的水平滚动量
        ( de && de.scrollLeft ) ||
    
        //最后,尝试取得body元素的水平滚动量
        document.body.scrollLeft;
}
//用来检测浏览器在垂直方向滚动了多少的函数
function scrollX() {
    //ie6 strict模式里的快捷方式
    var de = document.documentElement;
    //如果浏览器的pageYOffset可用,则使用之
    return self.pageYOffset ||
    
        //否则,尝试取得根节点的垂直滚动量
        ( de && de.scrollTop ) ||
    
        //最后,尝试取得body元素的垂直滚动量
        document.body.scrollTop;
}

   移动滚动条
  拥有了页面中滚条的偏移量和页面本身的长度信息之后,就可以利用浏览器提供的scrollTo方法,调整页面上的视口的当前位置。
  scrollTop方法作为window对象(以及任何其它包含可滚动内容元素的元素或者