11.HTML5 JavaScript DOM

来源:互联网 发布:网络键盘侠800作文 编辑:程序博客网 时间:2024/06/07 23:34

1. DOM事件模型
在进行js编程时,需要考虑两种编程模型:
  • IE模型
  • DOM模型,行业规范。

1.1 绑定事件处理
1.1.1 IE模型:objTarget.attachEvent("eventType" , handler);  

1.1.2 DOM提供的事件绑定方法:objTarget.addEventListener("eventType",handler,captureFlag)
  • eventType:事件类型,事件属性去掉"on"
  • handler:
  • captureFlag:true表示监听捕获阶段;false表示冒泡阶段。
DOM提供的事件解绑方法:objTarget.removeEventListener("eventType",handler,captureFlag)
<body><!-- 将测试的div元素 --><div id="test"><!-- div元素的子元素:按钮 --><input id="testbn" type="button" value="单击我" /></div><hr /><div id="results"> </div><script type="text/javascript">var gotClick1 = function(event) {document.getElementById("results").innerHTML += "事件捕获阶段: " + event.currentTarget + "<br />";}function gotClick2(event) {document.getElementById("results").innerHTML += "事件冒泡阶段:" + event.currentTarget + "<br />";}document.getElementById("testbn").addEventListener("click" , gotClick1 , true); // 为testbn按钮绑定事件处理函数(捕获阶段)document.getElementById("test").addEventListener("click" , gotClick1 , true); // 为test对象绑定事件处理函数(捕获阶段)document.getElementById("testbn").addEventListener("click" , gotClick2 , false); // 为testbn按钮绑定事件处理函数(冒泡阶段)document.getElementById("test").addEventListener("click" , gotClick2 , false);// 为按钮所在的div对象绑定事件处理函数(冒泡阶段)。</script></body>

事件捕获阶段的两个函数先触发,先触发"div"元素;
事件冒泡阶段的两个函数后触发,先触发"input"元素;


1.2 访问事件对象
event.target.innerHTML
在DOM事件模型中,浏览器会将单击事件封装成Event对象,并将该对象传给clickHandler()的evt参数。
<body><button id="a">按钮</button><script type="text/javascript">var clickHandler = function(evt){alert(evt.target.innerHTML);//按钮}document.getElementById("a").onclick = clickHandler;</script></body>



DOM事件模型和IE事件模型访问事件对象的方式完全不同,如果需要写一个跨浏览器的程序,容易的做法:
将事件处理函数绑定到HTML元素,并将event显示作为参数传入事件处理函数。
但是这种方法不好。
推荐做法,将事件处理函数绑定到DOM对象的属性,也一样可以实现跨浏览器。

由于IE事件模型和DOM事件模型存在差异,
为了更好的实现跨浏览器,在访问这些有冲突的对象、属性、方法之前,应首先判断该浏览器是否支持该对象、属性、方法。

clickHandler()函数的形参名不能叫event,
如果该函数的形参名叫event,则该形参将会覆盖全局可用的event对象,从而可能导致在IE中不能访问事件对象。

<body><button id="a">按钮</button><script type="text/javascript">// 定义一个形参evtvar clickHandler = function(evt){// 对于DOM事件模型,访问事件源用target属性if (evt){alert(evt.target.innerHTML);}// 对于IE浏览器else{alert(window.event.srcElement.innerHTML);}}// 为按钮a绑定事件处理器document.getElementById("a").onclick = clickHandler;</script></body>







1.3 DOM事件继承体系:
Event
MultationEventUIEvent
MouseEvent


Table 17-2. Event modules, interfaces, and types

Module name

Event interface

Event types

HTMLEvents

Event

abort, blur, change, error, focus, load, reset, resize, scroll, select, submit, unload

MouseEvents

MouseEvent

click, mousedown, mousemove, mouseout, mouseover, mouseup

UIEvents

UIEvent

DOMActivate, DOMFocusIn, DOMFocusOut


1.3.1 Event 对象

Event 对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。

事件通常与函数结合使用,函数不会在事件发生前被执行!

IE: Internet Explorer, F: Firefox, O: Opera, W3C: W3C 标准.

事件句柄 (Event Handlers)

HTML 4.0 的新特性之一是能够使 HTML 事件触发浏览器中的行为,比如当用户点击某个 HTML 元素时启动一段 JavaScript。下面是一个属性列表,可将之插入 HTML 标签以定义事件的行为。

属性此事件发生在何时...IEFOW3Conabort图像的加载被中断。419Yesonblur元素失去焦点。319Yesonchange域的内容被改变。319Yesonclick当用户点击某个对象时调用的事件句柄。319Yesondblclick当用户双击某个对象时调用的事件句柄。419Yesonerror在加载文档或图像时发生错误。419Yesonfocus元素获得焦点。319Yesonkeydown某个键盘按键被按下。31NoYesonkeypress某个键盘按键被按下并松开。319Yesonkeyup某个键盘按键被松开。319Yesonload一张页面或一幅图像完成加载。319Yesonmousedown鼠标按钮被按下。419Yesonmousemove鼠标被移动。319Yesonmouseout鼠标从某元素移开。419Yesonmouseover鼠标移到某元素之上。319Yesonmouseup鼠标按键被松开。419Yesonreset重置按钮被点击。419Yesonresize窗口或框架被重新调整大小。419Yesonselect文本被选中。319Yesonsubmit确认按钮被点击。319Yesonunload用户退出页面。319Yes

鼠标 / 键盘属性

属性描述IEFOW3CaltKey返回当事件被触发时,"ALT" 是否被按下。619Yesbutton返回当事件被触发时,哪个鼠标按钮被点击。619YesclientX返回当事件被触发时,鼠标指针的水平坐标。619YesclientY返回当事件被触发时,鼠标指针的垂直坐标。619YesctrlKey返回当事件被触发时,"CTRL" 键是否被按下。619YesmetaKey返回当事件被触发时,"meta" 键是否被按下。No19YesrelatedTarget返回与事件的目标节点相关的节点。No19YesscreenX返回当某个事件被触发时,鼠标指针的水平坐标。619YesscreenY返回当某个事件被触发时,鼠标指针的垂直坐标。619YesshiftKey返回当事件被触发时,"SHIFT" 键是否被按下。619Yes

IE 属性

除了上面的鼠标/事件属性,IE 浏览器还支持下面的属性:

属性描述cancelBubble如果事件句柄想阻止事件传播到包容对象,必须把该属性设为 true。fromElement对于 mouseover 和 mouseout 事件,fromElement 引用移出鼠标的元素。keyCode对于 keypress 事件,该属性声明了被敲击的键生成的 Unicode 字符码。对于 keydown 和 keyup 事件,它指定了被敲击的键的虚拟键盘码。虚拟键盘码可能和使用的键盘的布局相关。offsetX,offsetY发生事件的地点在事件源元素的坐标系统中的 x 坐标和 y 坐标。returnValue如果设置了该属性,它的值比事件句柄的返回值优先级高。把这个属性设置为 fasle,可以取消发生事件的源元素的默认动作。srcElement对于生成事件的 Window 对象、Document 对象或 Element 对象的引用。toElement对于 mouseover 和 mouseout 事件,该属性引用移入鼠标的元素。x,y事件发生的位置的 x 坐标和 y 坐标,它们相对于用CSS动态定位的最内层包容元素。

标准 Event 属性

下面列出了 2 级 DOM 事件标准定义的属性。

属性描述IEFOW3Cbubbles返回布尔值,指示事件是否是起泡事件类型。No19Yescancelable返回布尔值,指示事件是否可拥可取消的默认动作。No19YescurrentTarget返回其事件监听器触发该事件的元素。No19YeseventPhase返回事件传播的当前阶段。   Yestarget返回触发此事件的元素(事件的目标节点)。No19YestimeStamp返回事件生成的日期和时间。No19Yestype返回当前 Event 对象表示的事件的名称。619Yes


标准 Event 方法

下面列出了 2 级 DOM 事件标准定义的方法。IE 的事件模型不支持这些方法:

方法描述IEFOW3CinitEvent()初始化新创建的 Event 对象的属性。No19YespreventDefault()通知浏览器不要执行与事件关联的默认动作。No19YesstopPropagation()不再派发事件。No19Yes



1.3.2 MultationEvent


事件:DOMAttrModified、DOMCharacterDataModified、DOMNodeInserted、DOMNodeInsertedIntoDocument、DOMNodeRemoved、DOMNodeRemovedFromDocument、DOMSubtreeModified等


1.3.3 UIEvent
事件:DOMActivate、DOMFocusIn、DOMFocusOut
属性
    • view: 发生事件的Window对象(视图对象)
    • detail:一个数字。提供事件的额外信息。对于click,mousedown,mouseup事件,这个字段代表点击的次数。1代表一次,2代表两次,3代表3次。(每次点击生成一次事件----detail值为2的鼠标事件之前总有detail值为1的鼠标事件)。对于DOMActivate事件,1表示为正常激活,2表示超级激活。(如双击鼠标或同时按下Shift键和Enter键)


1.3.4 MouseEvent
事件:click、mousedown、mouseup、mouseover、mouseout、mousemove等
属性:
    • button: 一个数字,0--左键,1--中间键,2--右键。
    • altKey,ctrlKey,shiftKey,metaKey:返回布尔值,是否同时按下Alt、Ctrl、Meta、Shift。
    • clientX,clientY: 声明鼠标在浏览器窗口的坐标
    • screenX,screenY: 声明鼠标针在屏幕左上角的坐标
    • relatedTarget: 引用与事件的目标节点相关的节点。(mouseover--鼠标离开的节点,mouseout--鼠标将进入的节点)



 
Table 17-3. Event types

Event type

Interface

Bubble

C

Supported by/detail properties

abort

Event

yes

no

<img><object>

blur

Event

no

no

<a><area><button><input><label><select><textarea>

change

Event

yes

no

<input><select><textarea>

click

MouseEvent

yes

yes

screenXscreenYclientXclientYaltKeyctrlKeyshiftKeymetaKeybuttondetail

error

Event

yes

no

<body><frameset><img><object>

focus

Event

no

no

<a><area><button><input><label><select><textarea>

load

Event

no

no

<body><frameset><iframe><img><object>

mousedown

MouseEvent

yes

yes

screenXscreenYclientXclientYaltKeyctrlKeyshiftKeymetaKeybuttondetail

mousemove

MouseEvent

yes

no

screenXscreenYclientXclientYaltKeyctrlKeyshiftKeymetaKey

mouseout

MouseEvent

yes

yes

screenXscreenYclientXclientYaltKeyctrlKeyshiftKeymetaKeyrelatedTarget

mouseover

MouseEvent

yes

yes

screenXscreenYclientXclientYaltKeyctrlKeyshiftKeymetaKeyrelatedTarget

mouseup

MouseEvent

yes

yes

screenXscreenYclientXclientYaltKeyctrlKeyshiftKeymetaKeybuttondetail

reset

Event

yes

no

<form>

resize

Event

yes

no

<body><frameset><iframe>

scroll

Event

yes

no

<body>

select

Event

yes

no

<input><textarea>

submit

Event

yes

yes

<form>

unload

Event

no

no

<body><frameset>

DOMActivate

UIEvent

yes

yes

detail

DOMFocusIn

UIEvent

yes

no

none

DOMFocusOut

UIEvent

yes

no

none




1.4 事件传播

冒泡事件流

事件传播——冒泡与捕获

DOM事件标准定义了两种事件流,这两种事件流有着显著的不同并且可能对你的应用有着相当大的影响。
这两种事件流分别是捕获和冒泡。
和许多Web技术一样,在它们成为标准之前,Netscape和微软各自不同地实现了它们。
Netscape选择实现了捕获事件流,微软则实现了冒泡事件流。
幸运的是,W3C决定组合使用这两种方法,并且大多数新浏览器都遵循这两种事件流方式。默认情况下,事件使用冒泡事件流,不使用捕获事件流。
然而,在Firefox和Safari里,你可以显式的指定使用捕获事件流,方法是在注册事件时传入useCapture参数,将这个参数设为true。

冒泡事件流

当事件在某一DOM元素被触发时,例如用户在客户名字节点上点击鼠标,事件将跟随着该节点继承自的各个父节点冒泡穿过整个的DOM节点层次,直到它遇到依附有该事件类型处理器的节点,此时,该事件是onclick事件。
在冒泡过程中的任何时候都可以终止事件的冒泡,在遵从W3C标准的浏览器里可以通过调用事件对象上的stopPropagation()方法,
在Internet Explorer里可以通过设置事件对象的cancelBubble属性为true。
如果不停止事件的传播,事件将一直通过DOM冒泡直至到达文档根。

捕获事件流

事件的处理将从DOM层次的根开始,而不是从触发事件的目标元素开始,事件被从目标元素的所有祖先元素依次往下传递。在这个过程中,事件会被从文档根到事件目标元素之间各个继承派生的元素所捕获,如果事件监听器在被注册时设置了useCapture属性为true,那么它们可以被分派给这期间的任何元素以对事件做出处理;否则,事件会被接着传递给派生元素路径上的下一元素,直至目标元素。事件到达目标元素后,它会接着通过DOM节点再进行冒泡。


<body>友情链接:<br /> <a id="mylink" href="http://www.crazyit.org">疯狂Java联盟</a><div id="show"></div><script type="text/javascript">// 事件捕获阶段的处理函数var killClick1 = function(event){// 取消默认事件的默认行为event.preventDefault();// 阻止事件传播//event.stopPropagation();document.getElementById("show").innerHTML += '事件捕获阶段' + event.currentTarget + "<br />";}//事件冒泡阶段的处理函数var killClick2 = function(event){// 取消事件的默认行为event.preventDefault();// 阻止事件传播//event.stopPropagation(); document.getElementById("show").innerHTML+= '事件冒泡阶段' + event.currentTarget + "<br />";}// 在事件捕获阶段,分别为超链接对象、document对象绑定事件处理函数。document.addEventListener("click", killClick1, true);document.getElementById("mylink").addEventListener("click", killClick1, true);// 在事件冒泡阶段,分别为超链接对象、document对象绑定事件处理函数。document.addEventListener("click", killClick2, false);document.getElementById("mylink").addEventListener("click", killClick2, false);</script></body>


跨浏览器的拖放效果。
判断浏览器是支持DOM事件模型还是支持IE事件模型。
if (event.preventDefault) {} else {}
if (document.addEventListener){}else if (document.attachEvent) {}

<body><!-- 导入JavaScript脚本文件 --><script src="drag.js"></script><!-- 定义被拖放的元素 --><div style="position:absolute; left:120px; top:150px; width:250px;  border:1px solid black;"><div style="background-color:#416ea5;  width:250px; height:22px; cursor:move; font-weight:bold; border-bottom:1px solid black;"onmousedown="drag(this.parentNode, event);">可拖动标题</div><p>可被拖动的窗口</p><p>窗口内容</p></div><!-- 定义一个可拖动的图片 --><img src="image/logo.jpg" alt="按住Shift可拖动" style="position:absolute;" onmousedown="if (event.shiftKey) drag(this, event);" /></body>

var drag = function(target, event){// 定义开始拖动时的鼠标位置(相对window座标)var startX = event.clientX;var startY = event.clientY;// 定义将要被拖动元素的位置(相对于document座标)// 因为该target的position为absolutely,// 所以我们认为它的座标系是基于document的var origX = target.offsetLeft;var origY = target.offsetTop;// 因为后面根据event的clientX、clientY来获取鼠标位置时,// 只能获取windows座标系的位置,所以需要计算window座标系// 和document座标系的偏移。// 计算windows座标系和document座标系之间的偏移var deltaX = startX - origX;var deltaY = startY - origY;// 鼠标松开的事件处理器var upHandler = function(evt) {// 对于IE事件模型,获取事件对象if (!evt) evt = window.event; // 取消被拖动对象的鼠标移动(mousemove)和鼠标松开(mouseup)的事件处理器if (document.removeEventListener){// DOM事件模型// 取消在事件捕获阶段的事件处理器document.removeEventListener("mouseup", upHandler, true);document.removeEventListener("mousemove", moveHandler, true);}else if (document.detachEvent) {target.detachEvent("onlosecapture", upHandler);target.detachEvent("onmouseup", upHandler);target.detachEvent("onmousemove", moveHandler);target.releaseCapture( );}// 阻止事件传播stopProp(evt);}// 阻止事件传播(该函数可以跨浏览器)var stopProp = function(evt){// DOM事件模型if (evt.stopPropagation){evt.stopPropagation( );}// IE事件模型else{evt.cancelBubble = true;}}// 为被拖动对象的鼠标移动(mousemove)和鼠标松开(mouseup)注册事件处理器if (document.addEventListener){// DOM事件模型// 在事件捕获阶段绑定事件处理器document.addEventListener("mousemove", moveHandler, true);document.addEventListener("mouseup", upHandler, true);}else if (document.attachEvent) {// IE事件模型// 设置该元素直接捕获该事件target.setCapture();// 为该元素鼠标移动时绑定事件处理器target.attachEvent("onmousemove", moveHandler);// 为鼠标松开时绑定事件处理器target.attachEvent("onmouseup", upHandler);// 将失去捕获事件当成鼠标松开处理。target.attachEvent("onlosecapture", upHandler);}// 阻止事件传播stopProp(event);// 取消事件默认行为if (event.preventDefault){// DOM事件模型event.preventDefault( ); }else{// IE事件模型event.returnValue = false;}// 鼠标移动的事件处理器function moveHandler(evt){// 对于IE事件模型,获取事件对象if (!evt) evt = window.event; // 将被拖动元素的位置移动到当前鼠标位置。// 先将window座标系位置转换成document座标系位置,再修改目标对象的CSS位置。target.style.left = (evt.clientX - deltaX) + "px";target.style.top = (evt.clientY - deltaY) + "px";// 阻止事件传播stopProp(evt);}}



1.5 转发事件
// 创建一个普通事件
var e = document.createEvent("Events");
// 初始化事件对象,指定该事件支持冒泡,不允许取消默认行为
e.initEvent("click", true, false);


e.initUIEvent

e.initMouseEvent


//将事件转发到target上
target.dispatchEvent(e);
<body><!-- 测试用的第一个按钮 --><input id="bn1" type="button" value="按钮1" /><!-- 测试用的第二个按钮 --><input id="bn2" type="button" value="按钮2" /><div id="show"></div><script type="text/javascript">// 第一个按钮被单击时的事件处理函数var rd = function(evt){document.getElementById("show").innerHTML+= '事件冒泡阶段:' + evt.currentTarget.value+ "被单击了<br />";// 创建一个普通事件var e = document.createEvent("Events");// 初始化事件对象,指定该事件支持冒泡,不允许取消默认行为e.initEvent("click", true, false);// 将事件转发到按钮bn2 document.getElementById("bn2").dispatchEvent(e);}// 第二个按钮被单击时的事件处理函数var gotClick = function(evt){document.getElementById("show").innerHTML+= '事件冒泡阶段:' + evt.currentTarget.value + "<br />";}// 分别为两个按钮绑定事件处理函数document.getElementById("bn1").addEventListener("click", rd, false);document.getElementById("bn2").addEventListener("click", gotClick, false);</script></body>


1.6 取消事件的默认行为


<body>友情链接: <a id="mylink" href="http://www.crazyit.org">疯狂Java联盟</a><script type="text/javascript">var killClicks = function(event){// 取消事件的默认行为event.preventDefault();alert("超链接被单击");}// 为按钮绑定事件处理函数(捕获阶段)document.getElementById("mylink").addEventListener("click", killClicks, true);</script></body>



event.preventDefault();取消了事件的默认行为,但是没有阻止事件处理函数的执行,也不会影响事件传播。
下面为超链接和document在事件传播阶段绑定了事件处理函数。
<body>友情链接: <a id="mylink" href="http://www.crazyit.org">疯狂Java联盟</a><!-- 显示信息输出的div元素 --><div id="show"></div><script type="text/javascript">var killClicks = function(event){// 取消事件的默认行为event.preventDefault();document.getElementById("show").innerHTML+= "事件捕获阶段:" + event.currentTarget + "<br>";}// 为document对象绑定事件处理函数document.addEventListener("click", killClicks, true);// 为超链接绑定事件处理函数document.getElementById("mylink").addEventListener("click", killClicks, true);</script></body>























0 0
原创粉丝点击