javascript中事件的理解
在javascript中,event事件是一个必不可少的讨论话题,它在和用户的交互中起到了很重要的作用。今天我们就来讨论一下JavaScript中的事
件处理,并且结合它来阐叙Ajax框架实现拖动效果的原理了。
一、 Event对象
1 Event对象的主要属性和方法
event代表事件的状态,专门负责对事件的处理,它的属性和方法能帮助我们完成很多和用户交互的操作,下面我们就来看看它的一些属性
和方法。
type:事件的类型,就是HTML标签属性中,没有“on”前缀之后的字符串,例如“Click”就代表单击事件。
srcElement:事件源,就是发生事件的元素。比如 < a onclick = " check() " ></ a > a这个链接是事件发生的源头,也就是该事件的srcElement
。
button:声明了被按下的鼠标键,是一个整数。0代表没有按键,1代表鼠标左键,2代表鼠标右键,4代表鼠标的中间键,如果按下了多个
鼠标键,就把这些值加在一起,所以3就代表左右键同时按下。
clientX / clientY:是指事件发生的时候,鼠标的横、纵坐标,返回的是整数,它们的值是相对于包容窗口的左上角生成的。
offsetX / offsetY:鼠标指针相对于源元素的位置,可以确定单击Image对象的哪个象素。
altKey,ctrlKey,shiftKey:顾名思义,这些属性是指鼠标事件发生的时候,是否同时按住了Alt、Ctrl或者Shift键,返回的是一个布尔
值。
keyCode:返回keydown和keyup事件发生的时候,按键的代码以及keypress事件的Unicode字符。比如event.keyCode = 13代表按下了回车键
;
fromElement、toElement前者是指代mouseover事件移动过的文档元素,后者指代mouseout事件中鼠标移动到的文档元素。
cancelBubble:一个布尔属性,把它设置为true的时候,将停止事件进一步起泡到包容层次的元素,它用于检测是否接受上层元素的事件
的控制。true代表不被上层元素的事件控制,false代表允许被上层元素的事件控制。
returnValue:一个布尔值属性,设置为false的时候可以阻止浏览器执行默认的事件动作,相当于 < a href = ”#” onclick = ”
ProcessMethod(); return false ;” /> 。
attachEvent()和detachEvent()方法:为制定DOM对象事件类型注册多个事件处理函数的方法,它们有两个参数,第一个是事件类型
,第二个是事件处理函数。在attachEvent()事件执行的时候,this关键字指向的是window对象,而不是发生事件的那个元素。
2 IE Event对象的一些说明
Event对象是一个全局属性
在IE中,不能把Event对象作为参数传递给事件处理程序,只能用window.event或者event来引用Event对象。因为在IE中,Event是window
的一个属性,也就是说event是一个全局变量,这个变量提供了事件的细节。
3 关于事件的起泡的概念
IE中事件的起泡:IE中事件可以沿着包容层次一点点起泡到上层,也就是说,下层的DOM节点定义的事件处理函数,到了上层的节点如
果还有和下层相同事件类型的事件处理函数,那么上层的事件处理函数也会执行。例如, < div > 标签包含了 < a > ,如果这两个标签都有 onclick
事件的处理函数,那么执行的情况就是先执行 < a > 标签的onclick事件处理函数,再执行 < div > 的事件处理函数。如果希望 < a > 的事件处理函数执
行完毕之后,不希望执行上层的 < div > 的onclick的事件处理函数了,那么就把 cancelBubble设置为false即可。
二、 IE中拖动DOM元素的例子
/*
该函数由mousedown事件处理调用
它为随后发生的mousemove和mouseup事件注册了临时的捕捉事件处理程序
并用这些事件处理程序拖动指定的文档元素
第二个参数必须是mousedown事件的事件对象
*/
function beginDrag(elementToDrag,event)
{
// 该元素当前位于何处
// 该元素的样式性质必须具有left和top css属性
// 此外,我们假定他们用象素做单位
// var x=parseInt(elementToDrag.style.left);
// var y=parseInt(elementToDrag.style.top);
// 计算一个点和鼠标点击之间的距离,下面的嵌套的moveHandler函数需要这些值
var deltaX = event.clientX - parseInt(elementToDrag.style.left);
var deltaY = event.clientY - parseInt(elementToDrag.style.top);
// 注册mousedown事件后发生的mousemove和mouseup事件的处理程序
// 注意,它们被注册为文档的捕捉事件处理程序
// 在鼠标按钮保持按下的状态的时候,这些事件处理程序保持活动的状态
// 在按钮被释放的时候,它们被删除
document.attachEvent( " onmousemove " ,moveHandler);
document.attachEvent( " onmouseup " ,upHandler);
// 我们已经处理了该事件,不要让别的元素看到它
event.cancelBubble = true ;
event.returnValue = false ;
/*
这是在元素被拖动时候捕捉mousemove事件的处理程序,它响应移动的元素
*/
function moveHandler(e)
{
// 把元素移动到当前的鼠标位置
e = window.event;
elementToDrag.style.left = (event.clientX - deltaX) + " px " ;
elementToDrag.style.top = (event.clientY - deltaY) + " px " ;
// 不要让别的元素看到该事件
event.cancelBubble = true ;
/*
该事件将捕捉拖动结束的时候发生的mouseup事件
*/
function upHandler(e)
{
// 注销事件处理程序
document.detachEvent( " onmouseup " ,upHandler);
document.detachEvent( " onmousemove " ,moveHandler);}
event.cancelBubble = true ;
}
调用它的HTML文件代码:
< html >
< head >
< title > Untitled Page </ title >
< script type = " text/javascript " src = " dragIE.js " ></ script >
</ head >
< body >
< div style = " position:absolute;left:100px;top:100px;background-color:White;border:solid black; " >
< div style = " background-color:Gray;border-bottom:solid black;padding:3px;font-family:Sans-Serif;font-weight:bold; "
onmousedown = " beginDrag(this.parentNode,event); " >
拖动我 & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;
</ div >
< div >
< p > This is a test.Testing,testing </ p ></ div >
</ div >
</ body >
三、 DOM中的高级事件处理
IE 6中的事件处理,并不是W3C DOM标准的事件处理模型,所以如果上述代码运行在Mozilla Firefox的浏览器中,就会失去作用,同时即将发
布的IE 7也将支持W3C DOM的二级标准,所以掌握DOM的高级事件处理显得就很重要了,因为W3C DOM二级标准是未来Web的发展方向,同时W3C
DOM的API非常常用,为未来更加复杂的Web开发提供了良好的基础。
(一)事件处理程序的作用域和事件的传播
在正式讨论DOM高级事件处理之前,我们有必要了解一下事件处理程序的作用域。事件处理程序的作用域要比普通的函数作用域复杂很多。
普通的函数作用域链比较容易,例如在一个普通函数中查找一个变量a,那么JavaScript解释器会先在该函数的调用对象中查找是否有a这个变
量,如果没有,将会在作用域链的下一个对象,一般是全局对象中查找。但是事件处理程序没这么简单,特别是用HTML的属性定义的,它们的
作用域链的头部是调用它们的对象,而下一个对象并不是全局对象,而是触发事件处理程序的对象。这样就会出现一个问题,window和
document都有一个方法open(),如果open()前面不加修饰,那么在事件处理的函数中将会调用document.open()方法,而不是常用的
window.open()方法,所以使用的时候应该明确指明是 window.open()。
(二)事件传播和注册事件处理程序
1 .事件传播
在二级DOM标准中,事件处理程序比较复杂,当事件发生的时候,目标节点的事件处理程序就会被触发执行,但是目标节点的父节点也有机
会来处理这个事件。事件的传播分为三个阶段,首先是捕捉阶段,事件从 Document对象沿着DOM树向下传播到目标节点,如果目标的任何一个
父节点注册了捕捉事件的处理程序,那么事件在传播的过程中就会首先运行这个程序。下一个阶段就是发生在目标节点自身了,注册在目标节
点上的相应的事件处理程序就会执行;最后是起泡阶段,事件将从目标节点向上传回给父节点,同样,如果父节点有相应的事件处理程序也会
处理。在IE中,没有捕捉的阶段,但是有起泡的阶段。可以用stopPropagating()方法来停止事件传播,也就是让其他元素对这个事件不可见,
在IE 6中,就是把cancelBubble设置为true。
2 .注册事件处理程序
和IE一样, DOM标准也有自己的事件处理程序,不过DOM二级标准的事件处理程序比IE的强大一些,事件处理程序的注册用
addEventListner方法,该方法有三个参数,第一个是事件类型,第二个是处理的函数,第三个是一个布尔值,true表示制定的事件处理程序将
在事件传播的阶段用于捕捉事件,否则就不捕捉,当事件发生在对象上才触发执行这个事件处理的函数,或者发生在该对象的字节点上,并且
向上起泡到这个对象上的时候,触发执行这个事件处理的函数。例如:document.addEventListener( " mousemove " ,moveHandler, true );就是在
mousemove事件发生的时候,调用moveHandler函数,并且可以捕捉事件。
可以用addEventListener为一个事件注册多个事件处理的程序,但是这些函数的执行顺序是不确定,并不像C#那样按照注册的顺序执行。
在Mozilla Firefox中用addEventListener注册一个事件处理程序的时候,this关键字就表示调用事件处理程序的文档元素,但是其他浏览器并
不一定是这样,因为这不是DOM标准,正确的做法是用currentTarget属性来引用调用事件处理程序的文档元素。
3 .二级DOM标准中的Event
和IE不同的是,W3C DOM中的Event对象并不是window全局对象下面的属性,换句话说,event不是全局变量。通常在DOM二级标准中,event作为
发生事件的文档对象的属性。Event含有两个子接口,分别是UIEvent和MutationEvent,这两个子接口实现了Event的所有方法和属性,而
MouseEvent接口又是UIEvent的子接口,所以实现了UIEvent和Event的所有方法和属性。下面,我们就看看Event、 UIEvent和MouseEvent的主
要属性和方法。
1 .Event
type:事件类型,和IE类似,但是没有“on”前缀,例如单击事件只是“click”。
target:发生事件的节点。
currentTarget:发生当前正在处理的事件的节点,可能是Target属性所指向的节点,也可能由于捕捉或者起泡,指向Target所指节点的
父节点。
eventPhase:指定了事件传播的阶段。是一个数字。
timeStamp:事件发生的时间。
bubbles:指明该事件是否起泡。
cancelable:指明该事件是否可以用preventDefault()方法来取消默认的动作。
preventDefault()方法:取消事件的默认动作;
stopPropagation()方法:停止事件传播。
2 .UIEvent
view:发生事件的window对象。
detail:提供事件的额外信息,对于单击事件、mousedown和mouseup事件都代表的是点击次数。
3 .MouseEvent
button:一个数字,指明在mousedown、mouseup和单击事件中,鼠标键的状态,和IE中的button属性类似,但是数字代表的意义不一样
,0代表左键,1代表中间键,2代表右键。
altKey、ctrlKey、shiftKey、metaKey:和IE相同,但是IE没有最后一个。
clientX、clientY:和IE的含义相同,但是在DOM标准中,这两个属性值都不考虑文档的滚动情况,也就是说,无论文档滚动到哪里,只要事件
发生在窗口左上角,clientX和clientY都是0,所以在IE中,要想得到事件发生的坐标相对于文档开头的位置,要加上
document.body.scrollLeft和document.body.scrollTop。
screenX、screenY:鼠标指针相对于显示器左上角的位置,如果你想打开新的窗口,这两个属性很重要。
relatedTarget:和IE中的fromElement、toElement类似,除了对于mouseover和mouseout有意义外,其他的事件没什么意义。
(三)兼容于两种主流浏览器的拖动DOM元素的例子
好了,刚才讲了这么多DOM编程和IE中的事件,那么如何编写兼容IE和Mozilla Firefox两种主流浏览器的拖拽程序呢?代码如下:
function beginDrag(elementToDrag,event)
{
var deltaX = event.clientX - parseInt(elementToDrag.style.left);
var deltaY = event.clientY - parseInt(elementToDrag.style.top);
if (document.addEventListener)
{
document.addEventListener( " mousemove " ,moveHandler, true );
document.addEventListener( " mouseup " ,upHandler, true );
}
else if (document.attachEvent)
{
document.attachEvent( " onmousemove " ,moveHandler);
document.attachEvent( " onmouseup " ,upHandler);
}
if (event.stopPropagation) event.stopPropagation();
else event.cancelBubble = true ;
if (event.preventDefault) event.preventDefault();
else event.returnValue = false ;
function moveHandler(e)
{
if ( ! e) e = window.event; // 如果是IE的事件对象,那么就用window.event
// 全局属性,否则就用DOM二级标准的Event对象。
elementToDrag.style.left = (event.clientX - deltaX) + " px " ;
elementToDrag.style.top = (event.clientY - deltaY) + " px " ;
if (event.stopPropagation) event.stopPropagation();
else event.cancelBubble = true ;
}
function upHandler(e)
{
if (document.removeEventListener)
{
document.removeEventListener( " mouseup " ,upHandler, true );
document.removeEventListener( " mousemove " ,moveHandler, true );}
else
{
document.detachEvent( " onmouseup " ,upHandler);
document.detachEvent( " onmousemove " ,moveHandler);}
}
if (event.stopPropagation) event.stopPropagation();
else event.cancelBubble = true ;
最后我们来回顾一下事件执行过程中的三个阶段:
1 捕捉阶段,事件从Document对象沿Dom解析的树向下传播给目标节点。
2 目标节点触发阶段 事件处理程序在目标上的运行阶段
3 起泡阶段 事件从目标元素向上传播或者起泡回Document对象的文档层次。
JavaScript获取网页中HTML元素的几种方法分析
getElementById getElementsByName getElementsByTagName 大概介绍
getElementById ,getElementsByName ,getElementsByTagName
后两个是得到集合,byid只是得到单个对象
getElementById 的用法
举个例子:
< a id = " link1 " name = " linkname1 " href = http: // homepage.yesky.com>网页陶吧</a>
同一页面内的引用方法:
1 、使用id:
link1.href,返回值为http: // homepage.yesky.com
2 、使用name:
document.all.linkname1.href,返回值为http: // homepage.yesky.com
3 、使用sourseIndex:
document.all( 4 ).href // 注意,前面还有HTML、HEAD、TITLE和BODY,所以是4
4 、使用链接集合:
document.anchors( 0 ).href
// 全部的集合有all、anchors、applets、areas、attributes、behaviorUrns、bookmarks、boundElements、cells、childNodes、
children、controlRange、elements、embeds、filters、forms、frames、images、imports、links、mimeTypes、options、plugins、rows、
rules、scripts、styleSheets、tBodies、TextRectangle,请参考MSDN介绍。
其实方法3和方法4是一样使用的集合,只是一个是all,可以包括页面所有标记,而anchors只包括链接。
5 、getElementById:
document.getElementById( " link1 " ).href
6 、getElementsByName:
document.getElementsByName( " linkname1 " )[ 0 ].href // 这也是一个集合,是所有name等于该方法所带参数的标记的集合
7 、getElementsByTagName:
document.getElementsByTagName( " A " )[ 0 ].href // 这也是一个集合,是所有标记名称等于该方法所带参数的标记的集合
8 、tags集合:
document.all.tags( " A " )[ 0 ].href
// 与方法7一样是按标记名称取得一个集合
除此之外:
event.scrElement可以获得触发时间的标记的引用;
document.elementFromPoint(x,y)可以获得x和y坐标处的元素的引用;
document.body.componentFromPoint(event.clientX,event.clientY)可以获得鼠标所在处元素的引用;
还可以通过元素的父子节点和兄弟节点关系来引用,如nextSibling(当前节点的后一节点)、previousSibling(当前节点的前一节点)、
childNodes、children、firstChild、lastChild、parentElement等都是父子节点和兄弟节点的一些引用;还不仅限于此。
上面是同一页面内的常见引用方法,另外还涉及到不同页面中的
getElementsByName返回的是所有name为指定值的所有元素的集合
“根据 NAME 标签属性的值获取对象的集合。”
集合比数组要松散的多, 集合里每个子项的类型可以不同, 集合只是把某些元素放在一起作为一类来使用, 相比之下数组就严格多了, 每
个子项都是统一的类型. document.getElementsByName, document.getElementsByTagName, document.formName.elements 这类方法所得到的
结果都是集合.
例:
< html >
< head >
< title > fish </ title >
< script language = " javascript " >
function get(){
var xx = document.getElementById( " bbs " )
alert( " 标记名称: " + xx.tagName);
}
function getElementName(){
var ele = document.getElementsByName( " happy " );
alert( " 无素为happy的个数: " + ele.length);
}
</ script ></ head >
< body >
< h2 id = " bbs " > 获取文件指定的元素 </ h2 >
< hr >
< form >
< input type = " button " onclick = " get() " value = " 获取标题标记 " >
< input type = " button " name = " happy " onclick = " getElementName() " value = " click " >
< input type = " button " name = " happy " onclick = " getElementName() " value = " click " >
< input type = " button " name = " happy " onclick = " getElementName() " value = " click " >
< input type = " button " name = " happy " onclick = " getElementName() " value = " click " >
< input type = " button " name = " happy " onclick = " getElementName() " value = " click " >
</ form >
</ body >
</ html >
document.getElementsByName()这个方法.它对一个和多个的处理是一样的,我们可以用:
Temp = document.getElementsByName( ' happy ' )来引用
当Temp只有1个的时候,那么就是Temp[ 0 ],有多个的时候,用下标法Temp[i]循环获取
也有例外:
在ie 中getElementsByName(“test“)的时候返回的是id = test的object数组,而firefox则返回的是name = test的object的数组。
按照w3c的规范应该是返回的是name = test的object的数组。
firefox和ie中的getElementByID相同:获取对 ID 标签属性为指定值的第一个对象的引用。
注意getElementsByName 有s在里面
document.getElementById()可以控制某个id的tag
document.getElementsByName(),返回的是一个具有相同 name 属性的元素的集合,而不是某个,注意有“s”。
而 document.getElementsByTagName() 返回的是一组相同 TAG 的元素集合。
同一个name可以有多个element,所以用document.getElementsByName( " theName " )
他return 一个collection,引用的时候要指名index
var test = document.getElementsByName( ' testButton ' )[ 0 ];
id那个,是唯一的
还应该注意:对类似没有name属性,对它name属性为伪属性document.getElementsByName() 会失效,当然TD可以设置ID属性,然后用
document.getElementsByID( " DDE_NODAY " ); 调用。
注:document.all 有些地方讲的不对。 document.all.tt1有可能是一个集合。
在javascript中,event事件是一个必不可少的讨论话题,它在和用户的交互中起到了很重要的作用。今天我们就来讨论一下JavaScript中的事
件处理,并且结合它来阐叙Ajax框架实现拖动效果的原理了。
一、 Event对象
1 Event对象的主要属性和方法
event代表事件的状态,专门负责对事件的处理,它的属性和方法能帮助我们完成很多和用户交互的操作,下面我们就来看看它的一些属性
和方法。
type:事件的类型,就是HTML标签属性中,没有“on”前缀之后的字符串,例如“Click”就代表单击事件。
srcElement:事件源,就是发生事件的元素。比如 < a onclick = " check() " ></ a > a这个链接是事件发生的源头,也就是该事件的srcElement
。
button:声明了被按下的鼠标键,是一个整数。0代表没有按键,1代表鼠标左键,2代表鼠标右键,4代表鼠标的中间键,如果按下了多个
鼠标键,就把这些值加在一起,所以3就代表左右键同时按下。
clientX / clientY:是指事件发生的时候,鼠标的横、纵坐标,返回的是整数,它们的值是相对于包容窗口的左上角生成的。
offsetX / offsetY:鼠标指针相对于源元素的位置,可以确定单击Image对象的哪个象素。
altKey,ctrlKey,shiftKey:顾名思义,这些属性是指鼠标事件发生的时候,是否同时按住了Alt、Ctrl或者Shift键,返回的是一个布尔
值。
keyCode:返回keydown和keyup事件发生的时候,按键的代码以及keypress事件的Unicode字符。比如event.keyCode = 13代表按下了回车键
;
fromElement、toElement前者是指代mouseover事件移动过的文档元素,后者指代mouseout事件中鼠标移动到的文档元素。
cancelBubble:一个布尔属性,把它设置为true的时候,将停止事件进一步起泡到包容层次的元素,它用于检测是否接受上层元素的事件
的控制。true代表不被上层元素的事件控制,false代表允许被上层元素的事件控制。
returnValue:一个布尔值属性,设置为false的时候可以阻止浏览器执行默认的事件动作,相当于 < a href = ”#” onclick = ”
ProcessMethod(); return false ;” /> 。
attachEvent()和detachEvent()方法:为制定DOM对象事件类型注册多个事件处理函数的方法,它们有两个参数,第一个是事件类型
,第二个是事件处理函数。在attachEvent()事件执行的时候,this关键字指向的是window对象,而不是发生事件的那个元素。
2 IE Event对象的一些说明
Event对象是一个全局属性
在IE中,不能把Event对象作为参数传递给事件处理程序,只能用window.event或者event来引用Event对象。因为在IE中,Event是window
的一个属性,也就是说event是一个全局变量,这个变量提供了事件的细节。
3 关于事件的起泡的概念
IE中事件的起泡:IE中事件可以沿着包容层次一点点起泡到上层,也就是说,下层的DOM节点定义的事件处理函数,到了上层的节点如
果还有和下层相同事件类型的事件处理函数,那么上层的事件处理函数也会执行。例如, < div > 标签包含了 < a > ,如果这两个标签都有 onclick
事件的处理函数,那么执行的情况就是先执行 < a > 标签的onclick事件处理函数,再执行 < div > 的事件处理函数。如果希望 < a > 的事件处理函数执
行完毕之后,不希望执行上层的 < div > 的onclick的事件处理函数了,那么就把 cancelBubble设置为false即可。
二、 IE中拖动DOM元素的例子
/*
该函数由mousedown事件处理调用
它为随后发生的mousemove和mouseup事件注册了临时的捕捉事件处理程序
并用这些事件处理程序拖动指定的文档元素
第二个参数必须是mousedown事件的事件对象
*/
function beginDrag(elementToDrag,event)
{
// 该元素当前位于何处
// 该元素的样式性质必须具有left和top css属性
// 此外,我们假定他们用象素做单位
// var x=parseInt(elementToDrag.style.left);
// var y=parseInt(elementToDrag.style.top);
// 计算一个点和鼠标点击之间的距离,下面的嵌套的moveHandler函数需要这些值
var deltaX = event.clientX - parseInt(elementToDrag.style.left);
var deltaY = event.clientY - parseInt(elementToDrag.style.top);
// 注册mousedown事件后发生的mousemove和mouseup事件的处理程序
// 注意,它们被注册为文档的捕捉事件处理程序
// 在鼠标按钮保持按下的状态的时候,这些事件处理程序保持活动的状态
// 在按钮被释放的时候,它们被删除
document.attachEvent( " onmousemove " ,moveHandler);
document.attachEvent( " onmouseup " ,upHandler);
// 我们已经处理了该事件,不要让别的元素看到它
event.cancelBubble = true ;
event.returnValue = false ;
/*
这是在元素被拖动时候捕捉mousemove事件的处理程序,它响应移动的元素
*/
function moveHandler(e)
{
// 把元素移动到当前的鼠标位置
e = window.event;
elementToDrag.style.left = (event.clientX - deltaX) + " px " ;
elementToDrag.style.top = (event.clientY - deltaY) + " px " ;
// 不要让别的元素看到该事件
event.cancelBubble = true ;
/*
该事件将捕捉拖动结束的时候发生的mouseup事件
*/
function upHandler(e)
{
// 注销事件处理程序
document.detachEvent( " onmouseup " ,upHandler);
document.detachEvent( " onmousemove " ,moveHandler);}
event.cancelBubble = true ;
}
调用它的HTML文件代码:
< html >
< head >
< title > Untitled Page </ title >
< script type = " text/javascript " src = " dragIE.js " ></ script >
</ head >
< body >
< div style = " position:absolute;left:100px;top:100px;background-color:White;border:solid black; " >
< div style = " background-color:Gray;border-bottom:solid black;padding:3px;font-family:Sans-Serif;font-weight:bold; "
onmousedown = " beginDrag(this.parentNode,event); " >
拖动我 & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;
</ div >
< div >
< p > This is a test.Testing,testing </ p ></ div >
</ div >
</ body >
三、 DOM中的高级事件处理
IE 6中的事件处理,并不是W3C DOM标准的事件处理模型,所以如果上述代码运行在Mozilla Firefox的浏览器中,就会失去作用,同时即将发
布的IE 7也将支持W3C DOM的二级标准,所以掌握DOM的高级事件处理显得就很重要了,因为W3C DOM二级标准是未来Web的发展方向,同时W3C
DOM的API非常常用,为未来更加复杂的Web开发提供了良好的基础。
(一)事件处理程序的作用域和事件的传播
在正式讨论DOM高级事件处理之前,我们有必要了解一下事件处理程序的作用域。事件处理程序的作用域要比普通的函数作用域复杂很多。
普通的函数作用域链比较容易,例如在一个普通函数中查找一个变量a,那么JavaScript解释器会先在该函数的调用对象中查找是否有a这个变
量,如果没有,将会在作用域链的下一个对象,一般是全局对象中查找。但是事件处理程序没这么简单,特别是用HTML的属性定义的,它们的
作用域链的头部是调用它们的对象,而下一个对象并不是全局对象,而是触发事件处理程序的对象。这样就会出现一个问题,window和
document都有一个方法open(),如果open()前面不加修饰,那么在事件处理的函数中将会调用document.open()方法,而不是常用的
window.open()方法,所以使用的时候应该明确指明是 window.open()。
(二)事件传播和注册事件处理程序
1 .事件传播
在二级DOM标准中,事件处理程序比较复杂,当事件发生的时候,目标节点的事件处理程序就会被触发执行,但是目标节点的父节点也有机
会来处理这个事件。事件的传播分为三个阶段,首先是捕捉阶段,事件从 Document对象沿着DOM树向下传播到目标节点,如果目标的任何一个
父节点注册了捕捉事件的处理程序,那么事件在传播的过程中就会首先运行这个程序。下一个阶段就是发生在目标节点自身了,注册在目标节
点上的相应的事件处理程序就会执行;最后是起泡阶段,事件将从目标节点向上传回给父节点,同样,如果父节点有相应的事件处理程序也会
处理。在IE中,没有捕捉的阶段,但是有起泡的阶段。可以用stopPropagating()方法来停止事件传播,也就是让其他元素对这个事件不可见,
在IE 6中,就是把cancelBubble设置为true。
2 .注册事件处理程序
和IE一样, DOM标准也有自己的事件处理程序,不过DOM二级标准的事件处理程序比IE的强大一些,事件处理程序的注册用
addEventListner方法,该方法有三个参数,第一个是事件类型,第二个是处理的函数,第三个是一个布尔值,true表示制定的事件处理程序将
在事件传播的阶段用于捕捉事件,否则就不捕捉,当事件发生在对象上才触发执行这个事件处理的函数,或者发生在该对象的字节点上,并且
向上起泡到这个对象上的时候,触发执行这个事件处理的函数。例如:document.addEventListener( " mousemove " ,moveHandler, true );就是在
mousemove事件发生的时候,调用moveHandler函数,并且可以捕捉事件。
可以用addEventListener为一个事件注册多个事件处理的程序,但是这些函数的执行顺序是不确定,并不像C#那样按照注册的顺序执行。
在Mozilla Firefox中用addEventListener注册一个事件处理程序的时候,this关键字就表示调用事件处理程序的文档元素,但是其他浏览器并
不一定是这样,因为这不是DOM标准,正确的做法是用currentTarget属性来引用调用事件处理程序的文档元素。
3 .二级DOM标准中的Event
和IE不同的是,W3C DOM中的Event对象并不是window全局对象下面的属性,换句话说,event不是全局变量。通常在DOM二级标准中,event作为
发生事件的文档对象的属性。Event含有两个子接口,分别是UIEvent和MutationEvent,这两个子接口实现了Event的所有方法和属性,而
MouseEvent接口又是UIEvent的子接口,所以实现了UIEvent和Event的所有方法和属性。下面,我们就看看Event、 UIEvent和MouseEvent的主
要属性和方法。
1 .Event
type:事件类型,和IE类似,但是没有“on”前缀,例如单击事件只是“click”。
target:发生事件的节点。
currentTarget:发生当前正在处理的事件的节点,可能是Target属性所指向的节点,也可能由于捕捉或者起泡,指向Target所指节点的
父节点。
eventPhase:指定了事件传播的阶段。是一个数字。
timeStamp:事件发生的时间。
bubbles:指明该事件是否起泡。
cancelable:指明该事件是否可以用preventDefault()方法来取消默认的动作。
preventDefault()方法:取消事件的默认动作;
stopPropagation()方法:停止事件传播。
2 .UIEvent
view:发生事件的window对象。
detail:提供事件的额外信息,对于单击事件、mousedown和mouseup事件都代表的是点击次数。
3 .MouseEvent
button:一个数字,指明在mousedown、mouseup和单击事件中,鼠标键的状态,和IE中的button属性类似,但是数字代表的意义不一样
,0代表左键,1代表中间键,2代表右键。
altKey、ctrlKey、shiftKey、metaKey:和IE相同,但是IE没有最后一个。
clientX、clientY:和IE的含义相同,但是在DOM标准中,这两个属性值都不考虑文档的滚动情况,也就是说,无论文档滚动到哪里,只要事件
发生在窗口左上角,clientX和clientY都是0,所以在IE中,要想得到事件发生的坐标相对于文档开头的位置,要加上
document.body.scrollLeft和document.body.scrollTop。
screenX、screenY:鼠标指针相对于显示器左上角的位置,如果你想打开新的窗口,这两个属性很重要。
relatedTarget:和IE中的fromElement、toElement类似,除了对于mouseover和mouseout有意义外,其他的事件没什么意义。
(三)兼容于两种主流浏览器的拖动DOM元素的例子
好了,刚才讲了这么多DOM编程和IE中的事件,那么如何编写兼容IE和Mozilla Firefox两种主流浏览器的拖拽程序呢?代码如下:
function beginDrag(elementToDrag,event)
{
var deltaX = event.clientX - parseInt(elementToDrag.style.left);
var deltaY = event.clientY - parseInt(elementToDrag.style.top);
if (document.addEventListener)
{
document.addEventListener( " mousemove " ,moveHandler, true );
document.addEventListener( " mouseup " ,upHandler, true );
}
else if (document.attachEvent)
{
document.attachEvent( " onmousemove " ,moveHandler);
document.attachEvent( " onmouseup " ,upHandler);
}
if (event.stopPropagation) event.stopPropagation();
else event.cancelBubble = true ;
if (event.preventDefault) event.preventDefault();
else event.returnValue = false ;
function moveHandler(e)
{
if ( ! e) e = window.event; // 如果是IE的事件对象,那么就用window.event
// 全局属性,否则就用DOM二级标准的Event对象。
elementToDrag.style.left = (event.clientX - deltaX) + " px " ;
elementToDrag.style.top = (event.clientY - deltaY) + " px " ;
if (event.stopPropagation) event.stopPropagation();
else event.cancelBubble = true ;
}
function upHandler(e)
{
if (document.removeEventListener)
{
document.removeEventListener( " mouseup " ,upHandler, true );
document.removeEventListener( " mousemove " ,moveHandler, true );}
else
{
document.detachEvent( " onmouseup " ,upHandler);
document.detachEvent( " onmousemove " ,moveHandler);}
}
if (event.stopPropagation) event.stopPropagation();
else event.cancelBubble = true ;
最后我们来回顾一下事件执行过程中的三个阶段:
1 捕捉阶段,事件从Document对象沿Dom解析的树向下传播给目标节点。
2 目标节点触发阶段 事件处理程序在目标上的运行阶段
3 起泡阶段 事件从目标元素向上传播或者起泡回Document对象的文档层次。
JavaScript获取网页中HTML元素的几种方法分析
getElementById getElementsByName getElementsByTagName 大概介绍
getElementById ,getElementsByName ,getElementsByTagName
后两个是得到集合,byid只是得到单个对象
getElementById 的用法
举个例子:
< a id = " link1 " name = " linkname1 " href = http: // homepage.yesky.com>网页陶吧</a>
同一页面内的引用方法:
1 、使用id:
link1.href,返回值为http: // homepage.yesky.com
2 、使用name:
document.all.linkname1.href,返回值为http: // homepage.yesky.com
3 、使用sourseIndex:
document.all( 4 ).href // 注意,前面还有HTML、HEAD、TITLE和BODY,所以是4
4 、使用链接集合:
document.anchors( 0 ).href
// 全部的集合有all、anchors、applets、areas、attributes、behaviorUrns、bookmarks、boundElements、cells、childNodes、
children、controlRange、elements、embeds、filters、forms、frames、images、imports、links、mimeTypes、options、plugins、rows、
rules、scripts、styleSheets、tBodies、TextRectangle,请参考MSDN介绍。
其实方法3和方法4是一样使用的集合,只是一个是all,可以包括页面所有标记,而anchors只包括链接。
5 、getElementById:
document.getElementById( " link1 " ).href
6 、getElementsByName:
document.getElementsByName( " linkname1 " )[ 0 ].href // 这也是一个集合,是所有name等于该方法所带参数的标记的集合
7 、getElementsByTagName:
document.getElementsByTagName( " A " )[ 0 ].href // 这也是一个集合,是所有标记名称等于该方法所带参数的标记的集合
8 、tags集合:
document.all.tags( " A " )[ 0 ].href
// 与方法7一样是按标记名称取得一个集合
除此之外:
event.scrElement可以获得触发时间的标记的引用;
document.elementFromPoint(x,y)可以获得x和y坐标处的元素的引用;
document.body.componentFromPoint(event.clientX,event.clientY)可以获得鼠标所在处元素的引用;
还可以通过元素的父子节点和兄弟节点关系来引用,如nextSibling(当前节点的后一节点)、previousSibling(当前节点的前一节点)、
childNodes、children、firstChild、lastChild、parentElement等都是父子节点和兄弟节点的一些引用;还不仅限于此。
上面是同一页面内的常见引用方法,另外还涉及到不同页面中的
getElementsByName返回的是所有name为指定值的所有元素的集合
“根据 NAME 标签属性的值获取对象的集合。”
集合比数组要松散的多, 集合里每个子项的类型可以不同, 集合只是把某些元素放在一起作为一类来使用, 相比之下数组就严格多了, 每
个子项都是统一的类型. document.getElementsByName, document.getElementsByTagName, document.formName.elements 这类方法所得到的
结果都是集合.
例:
< html >
< head >
< title > fish </ title >
< script language = " javascript " >
function get(){
var xx = document.getElementById( " bbs " )
alert( " 标记名称: " + xx.tagName);
}
function getElementName(){
var ele = document.getElementsByName( " happy " );
alert( " 无素为happy的个数: " + ele.length);
}
</ script ></ head >
< body >
< h2 id = " bbs " > 获取文件指定的元素 </ h2 >
< hr >
< form >
< input type = " button " onclick = " get() " value = " 获取标题标记 " >
< input type = " button " name = " happy " onclick = " getElementName() " value = " click " >
< input type = " button " name = " happy " onclick = " getElementName() " value = " click " >
< input type = " button " name = " happy " onclick = " getElementName() " value = " click " >
< input type = " button " name = " happy " onclick = " getElementName() " value = " click " >
< input type = " button " name = " happy " onclick = " getElementName() " value = " click " >
</ form >
</ body >
</ html >
document.getElementsByName()这个方法.它对一个和多个的处理是一样的,我们可以用:
Temp = document.getElementsByName( ' happy ' )来引用
当Temp只有1个的时候,那么就是Temp[ 0 ],有多个的时候,用下标法Temp[i]循环获取
也有例外:
在ie 中getElementsByName(“test“)的时候返回的是id = test的object数组,而firefox则返回的是name = test的object的数组。
按照w3c的规范应该是返回的是name = test的object的数组。
firefox和ie中的getElementByID相同:获取对 ID 标签属性为指定值的第一个对象的引用。
注意getElementsByName 有s在里面
document.getElementById()可以控制某个id的tag
document.getElementsByName(),返回的是一个具有相同 name 属性的元素的集合,而不是某个,注意有“s”。
而 document.getElementsByTagName() 返回的是一组相同 TAG 的元素集合。
同一个name可以有多个element,所以用document.getElementsByName( " theName " )
他return 一个collection,引用的时候要指名index
var test = document.getElementsByName( ' testButton ' )[ 0 ];
id那个,是唯一的
还应该注意:对类似没有name属性,对它name属性为伪属性document.getElementsByName() 会失效,当然TD可以设置ID属性,然后用
document.getElementsByID( " DDE_NODAY " ); 调用。
注:document.all 有些地方讲的不对。 document.all.tt1有可能是一个集合。