七、捕获事件
(一)事件
以上为基本事件,事件处理程序的名称只是在事件名称前面加上一个前缀‘on’。
(二)0级事件处理
内联模式即以属性的形式为HTML元素添加属性的方法
window.οnlοad=hello;
传统模式即通过对象属性将一个函数指定为事件处理程序。如果想禁用事件处理,可以将事件处理程序的值附为NULL。
注:在DOM Level 0 事件模型中,任何对象只允许指定一个事件处理程序,因此指定的函数不会累加。内联事件可以在所有浏览器中正常使用,但仍然应该限制使用。
1.Event对象
Event对象是和所有事件相关的。它有一些用来提供Event相关信息的属性,如Web页面中鼠标单击的位置。IE将Event视为window对象的属性。当处理事件时,将通过程序访问window对象。
event.altkey;
event.clientX;
event.clientY;
event.ctrlKey;
event.keyCode;
event.screenX;
event.screenY;
event.shiftKey;
event.type;
以上是event对象提供的属性且跨浏览器兼容的
2.事件冒泡
在事件冒泡中,最内部的元素将首先触发其事件,然后是栈内的下一个元素触发该事件,直到到达其最外面的元素。如果把事件处理程序指定给所有元素,那么这些事件将依次触发。如果要取消一个事件冒泡,可以用cancelBubble属性或stopPropagation方法。
function stopEvent (evnt) {
if (evnt.stopPropagation) {
evnt.stopPropagation();
} else{
evnt.cancelBubble = true;
}
}
cancelBubble方法用来阻止事件冒泡到IE浏览器还能捕获该事件的其他元素上。stopPropagation方法用来在其他浏览器上完成相同的工作。
注:检查的是stopPropagation函数是否存在,而不是检查cancelBubble函数是否存在,因为如果cancelBubble的值为false或该属性不存在,都会返回false。
3.事件处理程序和this
JavaScript
this关键字表示的是当前调用的函数或方法的所有者。对于全局函数而言,它表示的是window对象。对于对象方法而言,它表示的是该对象的实例。在事件处理程序中,它表示的就是接收到该事件的元素。
(三)DOM Level 2事件模型
与老事件模型的最主要区别在于新模型不依赖于特定的事件处理程序属性,对任何一个对象的任何一种事件注册多个事件处理程序函数。用来代替事件处理程序属性的是每个对象提供的 3个方法:
object.addEventListener('event',eventFunction,boolean);
第一个参数是click,load之类的事件;第二个参数是指定的事件处理程序函数;第三个参数用来指定事件是前远后近(cascadeDown)或冒泡(bubbleUp)模式处理的。如果是false,那这个事件将以冒泡处理,否则将把这个监听器改成事件捕获模型。
document.addEventListener('click',casecadeDown,true);
document.forms[0].addEventListener('click',casecadeDown,true);
document.forms[0].elements[0].addEventListener('click',casecadeDown,true);
document.addEventListener('click',bubbleUp,false);
document.forms[0].addEventListener('click',bubbleUp,false);
document.forms[0].elements[0].addEventListener('click',bubbleUp,false);
当应用程序捕获到第一次处理的事件时,将依次调用文档、表单和提交按钮的处理程序。冒泡阶段则是从提交按钮开始,然后是表单,最后是文档。
document.forms[0].elements[0].removeEventListener('click',casecadeDown,true);
彻底删除一个事件监听器,可以使用remove方法,当事件开始处理时,该方法是无法正常运作的,不过当下一次单击提交按钮时,针对这个表单元素的捕获事件处理程序将不会再调用。
object.attachEvent("eventhandler",function);
object.detachEvent("eventhandler",function);
与addEventListener和removeEventListener方法相似的分别是attachEvent和detachEvent。第一个参数是事件处理程序onclick,onload之类的,第二个是函数。
八、表单、表单事件及验证
表单是页面元素的一种,它是以数组形式组织的,附加在文档中。将所在位置减1就是其在数组中的索引值。更好的方法是为表单设置一个标识符,然后使用document对象的getElementById方法访问它。
(一)为表单添加事件
document.getElementById("someform").onsubmit = formHandler;
不管采用哪种方法,都要取消提交操作,需在事件处理程序函数中返回false即可。
取消一个事件
function stopEvent (evnt) {
var event = evnt? evnt : window.event;
if (event.preventDefault) {
event.preventDefault();
event.stopPropagation();
} else{
event.returnValue = false;
event.cancelBubble = true;
}
}
returnValue属性相当于在函数中显式地返回false值。preventDefault函数则是用来阻止基于该元素和事件的默认行为。
(二)选择列表框元素(select option)
var slIdx = document.getElementById("formname").theSelection.selectedIndex;
var opt = document.getElementById("formname").theSelection.options[slIdx];
如果用户只能选择一个选项,那么可以直接找到下标返回数组中的特定选项。
var opts = document.getElementById("formname").theSelection.options;
for (var i = 0; i < opts.length; i++) {
if(opts[i].selected){
alert(opts[i].text);
}
return false;
}
如果可以选择多个选项,那么代码就需要遍历整个opts数组,以检查哪些是选中的
function catchEvent (eventObj,event,function) {
if (eventObj.addEventListener) {
eventObj.addEventListener(event,function,false);
} else if(eventObj.attachEvent){
event = "on"+event;
eventObj.attachEvent(event,function);
}
}
当需要捕获许多事件时,可以采用复用的catchEvent方法,传入对象、事件和函数作为其函数。
动态修改选择列表框
opts[opts.length] = new Option("text","value");
在数组的最后面添加一个新的array元素
opts[2] = null;
opts.length = 0;
要删除一个选项,只要设置为null即可,这样操作会重置数组,而不会导致编号出现不连续现象。 如果要删除所有的选项,只需将数组的length设置为0即可。
自动选择选择列表框
if (opts[i].selected) {
switch(opts[i].value){
case"opt1" : opts[i+1].selected = true;break;
case"opt3" : opts[i+1].selected = true;break;
case"opt4" : opts[i+1].selected = true;break;
}
}
自动选择是即时验证的一种形式,要知道选择逻辑上成组的选项,并且禁用不合适的选项。
(三)单选按钮(radio button)和复选框(checkbox)
它们所提供的选项数通常要比选择列表框少。而单选按钮中一次只能选择一项,在复选框中一次可以选择多项。
var buttons = document.getElementById("radiogroup");
for (var i = 0; i < buttons.length; i++) {
if(button[i].checked){
alert(button[i].value);
}
}
注:单选按钮提供的所有选项的名称是一样的,实际上是一个成组的按钮。
var Opts = document.getElementsByTagName("input");
var isChecked = false;
for (var i = 0; i < Opts.length; i++) {
if((Opts[i].checked)&&(Opts[i].type="checkbox")){
isChecked = true;
}
}
getElementsByTagName方法将返回指定元素类型的所有项,可以获取整个页面中指定类型的所有元素。
(四)文本框(text)、文本区域(textarea)、密码框(password)和隐藏表单字段的输入元素
(五)input元素字段和基于正则表达式的验证
if (window.addEventListener) {
window.addEventListener("load",setupEvents,false);
} else if(window.attachEvent){
window.attachEvent("onload",setupEvents);
}else{
window.onload = setupEvents;
}
function setupEvents (evnt) {
document.someform.onsubmit = validateField;
}
function validateField(evnt){
var rgEx = new RegExp(document.someform.text1.value)
var OK = rgEx.exec(document.someform.text2.value)
if (!OK) {
document.someform.text3.value = "not a match";
} else{
document.someform.text3.value = "matched";
}
}
Jit RegEx Machine 应用程序,从一个字段中获取一个正则表达式,再从另一个字段中获取字符串,然后在表单提交时进行模式匹配,将其结果输出到第三个字段中。
(六)表单、沙箱和XSS
沙箱是一个受限的环境,使脚本无法访问浏览器所在计算机中的资源。浏览器所实现的安全限制要远远多于JavaScript语言所实现的机制,同时定义了一个针对浏览器的安全策略,用来判断脚本是否能够执行。XSS(跨网站脚本)是最严重的一个会影响安全的类,可以导致cookie信息失窃,客户端或网站的数据泄露。