【学习笔记九】

来源:互联网 发布:网络储备人才招聘 编辑:程序博客网 时间:2024/06/14 18:29

写在前面:

这篇是《js高程》13.4-13.6和14.1-14.4的笔记,记在网上也是方便自己以后随时随地可以回看。

13章前面的内容在 JS冒泡与捕获 那篇单独拎出来整理了。

其他详见代码注释 : )


PS :前面的EventUtil具体怎么来的可以看冒泡和捕获那篇↑


var EventUtil={  addHandler:function(element,type,handler){    if(element.addEventListener){      element.addEventListener(type,handler,false);    }else if(element.attachEvent){      element.attachEvent('on'+type,handler);    }else{      element['on'+type]=handler;    }  },  getEvent:function(event){    return event?event:window.event;  },  getTarget:function(event){    return event.target||event.srcElement;  },  preventDefault:function(event){    if(event.preventDefault){      event.preventDefault();    }else{      event.returnValue=false;    }  },  removeHandler:function(element,type,handler){    if(element.removeEventListener){      element.removeEventListener(type,handler,false);    }else(element.detachEvent){      element.detachEvent('on'+type,handler);    }else{      element['on'+type]=null;    }  },  stopPropagation:function(event){    if(event.stopPropagation){      event.stopPropagation();    }else{      event.cancelBubble=true;    }  }};


【事件类型】


// UI事件-load\unloadvar isSupport=document.implementation.hasFeature('HTMLEvents','2.0');//两种指定方式//一:js,推荐//这里传入的event对象不包含有关这个事件的任何附加信息,//但在兼容DOM的浏览器中event.target被设为document,//而IE并不会为这个事件设置srcElement属性EventUtil.addHandler(window,'load',function(event){  alert('Loaded!');});//二:向后兼容 <body onload="alert('...')">//在图像上触发load时,要先指定事件再指定src,因为图像在指定src属性后就会开始下载EventUtil.addHandler(window,'load',function(){  //先向window添加load,因为要在dom中添加新元素,首先要确保文档加载完毕  var image=document.createElement('img');  EventUtil.addHandler(image,'load',function(event){    event=EventUtil.getEvent(event);    alert(EventUtil.getTarget(event).src);  });  document.body.appendChild(image);  image.src='...';});//注:在不属于DOM文档的图像上触发load,IE8及以前版本不会生产event对象//IE9+、Firefox、Opera、Chrome、Safari3+中,<script>也可触发load//不同于img,只有在设置了<script>的src属性并将添加到文档后,才会开始下载js文件//所以指定事件处理程序和src属性的先后顺序就不重要//IE和Opera支持<link>上的load,未指定href并添加到文档之前也不会下载样式表EventUtil.addHandler(window,'unload',function(event){  alert('Unloaded!');});//生成的event对象在兼容dom的浏览器中只包含target,IE8及以前提供了srcElement
//鼠标与滚轮事件//dom通过event的relatedTarget属性提供相关元素信息,//这个属性只对mouseover、mouseout才包含值,对其他事件来说为null,//IE8及以前不支持relatedTarget,但在mouseover中有fromElement,在mouseout中有toElement//添加取得相关元素方法:var EventUtil={  //...其他代码  getRelatedTarget:function(event){    if(event.relatedTarget){      return event.relatedTarget;    }else if(event.toElement){      return event.toElement;    }else if(event.fromElement){      return event.fromElement;    }else{      return null;    }  },  //...};var div=document.getElementById('myDiv');EventUtil.addHandler(div,'mouseout',function(event){  event=EventUtil.getEvent(event);  var target=EventUtil.getTarget(event);  var relatedTarget=EventUtil.getRelatedTarget(event);  alert('moused out of'+target.tagName+'to'+relatedTarget.tagName);});//鼠标按钮//对mouseup和mousedown,event有一个button属性://值为0表示左键,1滚轮,2右键//IE8及以前://0没有按,1左键,2右键,3左右,4滚轮,5左键滚轮,6右键滚轮,7左右滚轮//Opera中不是操作左键不会触发mouseup和mousedownvar EventUtil={  //...  getButton:function(event){    if(document.implementation.hasFeature('MouseEvents','2.0')){      return event.button;    }else{      switch(event.button){        case 0:        case 1:        case 3:        case 5:        case 7:          return 0;//01357都返回0        case 2:        case 6:          return 2;//26都返回2        case 4:          return 1;//4返回1      }    }  },  //...};var div=document.getElementById('myDiv');EventUtil.addHandler(div,'mousedown',function(event){  event=EventUtil.getEvent(event);  alert(EventUtil.getButton(event));});//鼠标滚轮事件//mousewheel事件对应的event有一个wheelDelta属性,向前滚动是值为120的倍数,向后-120的倍数//Opera9.5以前正负相反//Firefox支持DOMMouseScroll事件,detail属性,向前是-3的倍数,向后3的倍数
//键盘与文本事件//IE9、Firefox、Chrome、Safari的event支持一个charCode属性,//只有在发生keypress时才包含值,保存按键代表字符ASCII码,//keyCode通常为0或按键键码;//IE8及以前和Opera则在keyCode中保存ASCII码;var EventUtil={  //...  getCharCode:function(event){    if(typeof event.charCode=='number'){      //先检查charCode是否包含数值,在不支持这个属性的浏览器中值为undefined      return event.charCode;    }else{      return event.keyCode;    }  },  //...};var textbox=document.getElementById('myText');EventUtil.addHandler(textbox,'keypress',function(event){  event=EventUtil.getEvent(event);  var ch=EventUtil.getCharCode(event);  alert(ch);  alert(String.fromCharCode(ch));  //取得字符编码后可用String.fromCharCode()将其转换成实际字符});
//HTML5事件//contextmenu事件,用以表示合适应该显示上下文菜单,冒泡,属于鼠标事件//IE、Firefox、Safari、Chrome、Opera 11+EventUtil.addHandler(window,'load',function(event){  var div=document.getElementById("myDiv");  EventUtil.addHandler(div,'contextmenu',function(event){    event=EventUtil.getEvent(event);    EventUtil.preventDefault(event);//取消浏览器默认菜单    var menu=document.getElementById('myMenu');    menu.style.left=event.clientX+'px';    menu.style.top=event.clientY+'px';//确定放置菜单(<ul>)的位置    menu.style.visibility='visible';//显示菜单  });  EventUtil.addHandler(document,'click',function(event){    document.getElementById('myMenu').style.visibility='hidden';  });//单词鼠标隐藏菜单});//beforeunload事件,在页面卸载操作之前阻止卸载操作//IE、Safari、Firefox、Chrome支持,但Opera11及以前不支持EventUtil.addHandler(window,'beforeunload',function(event){  event=EventUtil.getEvent(event);  var message="Sure to navigate away from this page?";  event.returnValue=message;//IE、Firefox  return message;//Safari、Chrome});

【内存与性能】


//事件委托,是对"事件处理程序过多"的解决方案,利用冒泡,只指定一个事件处理程序,管理某一类型所以事件。//最适合采用事件委托的事件有:click、mousedown、mouseup、keydown、keyup、keypress//如果可行,也可在document对象上添加一个事件处理程序,用以处理某种特定类型的事件/*<ul id="myLinks">  <li id="goSomewhere">Go somewhere</li>  <li id="doSomething">Do something</li>  <li id="sayHi">Say hi</li></ul> */var list=document.getElementById('myLinks');EventUtil.addHandler(list,"click",function(event){  event=EventUtil.getEvent(event);  var target=EventUtil.getTarget(event);  switch(target.id){    case "doSomething":      document.title="I changed the document's title";      break;    case "goSomewhere":      location.href="http://www.wrox.com";      break;    case "sayHi":      alert("hi");      break;  }});//移除事件处理程序//内存中留有那些过时不用的"空事件处理程序"的两种原因://1、从文档中移除带事件处理程序的元素,如纯粹DOM操作:removeChild()、replaceChild(),或用innerHTML替换  btn.onclick=function(){    btn.onclick=null;//先移除事件处理程序再替换    document.getElementById("myDiv").innerHTML="...";  };//注:在事件处理程序中删除按钮也能阻止事件冒泡,元素在文档中是冒泡的前提//2、卸载页面时(可能是在两个页面来回切换或刷新),内存中滞留的对象数目会增加//  最好的做法是,卸载之前先通过onunload事件处理程序移除所有事件处理程序


【模拟事件】


//可用js在任意时刻触发特定事件,在测试时非常有用//DOM中的事件模拟//在document对象上使用createEvent()创建event对象,接收一个参数,表示要创建事件类型的字符串//如:UIEvents\MouseEvents\MutationEvents\HTMLEvents//调用dispatchEvent()触发事件,接收一个参数,表示要触发事件的event对象,这样触发的事件照样冒泡//模拟鼠标事件//创建的对象有一个initMouseEvent()方法,用于指定与该鼠标事件有关的信息,接收15个参数,前5个为://type要触发的事件类型、bubbles是否冒泡、cancelable是否可以取消、view与事件关联的视图、detail与事件有关的详细信息var btn=document.getElementById("myBtn");var event=document.createEvent("MouseEvents");//初始化对象event.initMouseEvent("click",true,true,document.defaultView,0,0,0,0,0,false,false,false,false,0,null);btn.dispatchEvent(event);//模拟键盘事件var textbox=document.getElementById("myTextbox"),event;//以DOM3级方式创建事件对象if(document.implementation.hasFeature("KeyboardEvents","3.0")){  event=document.createEvent("KeyboardEvent");  event.initKeyboardEvent("keydown",true,true,document.defaultView,"a",0,"Shift",0);  //'a' 按下的键码-按下了哪里的键,0是主键盘-空调图-在一行中按了多少次这个键,0}textbox.dispatchEvent(event);//在Firefox中var textbox=document.getElementById("myTextbox"),event;event=document.createEvent("KeyEvents");event.initKeyEvent('keypress',true,true,document.defaultView,false,false,false,false,65,65);//ctrl-alt-shift-meta-keyCode键码-charCode ASCII码textbox.dispatchEvent(event);//其他浏览器中,创建一个通用的事件var textbox=document.getElementById("myTextbox"),event;event=document.createEvent("Events");event.initEvent(type,bubbles,cancelable);event.view=document.defaultView;event.altKey=false;event.ctrlKey=false;event.shiftKey=false;event.metaKey=false;event.keyCode=65;event.charCode=65;textbox.dispatchEvent(event);//像这样模拟事件虽然会触发键盘事件,但却不会向文本框中写入文本,这是由于无法精确模拟键盘事件造成的//DOM3还定义了自定义事件,调用createEvent("CustomEvent"),//返回的对象有一个initCustomEvent()方法,接收四个参数://type、bubbles、cancelable、detail//IE9+、Firefox6+var div=document.getElementById('myDiv'),event;EventUtil.addHandler(div,'myevent',function(event){  alert('DIV:'+event.detail);});EventUtil.addHandler(document,"myevent",function(event){  alert('DOCUMENT:'+event.detail);});if(document,implementation.hasFeature("CustomEvents","3.0")){  event=document.createEvent("CustomEvent");  event.initCustomEvent("myevent",true,false,"hello world!");  div.dispatchEvent(event);}//IE中的事件模拟//调用document.createEventObject(),无参数,返回一个通用event对象,要手动添加必要信息,//在目标上调用fireEvent()方法,接收两个参数:事件处理程序名称和event对象,//在调用这个方法时会自动为event对象添加srcElement和type属性,其他属性手动添加var btn=document.getElementById('myBtn');var event=document.createEventObject();event.screenX=100;event.screenY=0;event.clientX=0;event.clientY=0;event.ctrlKey=false;event.altKey=false;event.shiftKey=false;event.button=0;btn.fireEvent("onclick",event);var textbox=document.getElementById("myTextbox");var event=document.createEventObject();event.altKey=false;event.ctrlKey=false;event.shiftKey=false;event.keyCode=65;textbox.fireEvent("onkeypress",event);



【表单基础】


//避免多次提交表单EventUtil.addHandler(form,'submit',function(event){event=EventUtil.getEvent(event);target=EventUtil.getTarget(event);var btn=target.elements['submit-btn'];btn.disabled=true;});
//focus()\blur()EventUtil.addHandler(window,'load',function(event){document.forms[0].elements[0].focus();});//如果第一个表单字段是<input>,且type为'hidden',上面代码会出错//如果css的display和visibility隐藏了该字段,同样致错//HTML5新增autofocus属性,自动把焦点移到相应字段//Firefox4+、Safari5+、Chrome、Opera9.6//<input type='text' autofocus>EventUtil.addHandler(window,'load',function(event){var element=document.forms[0].elements[0];if(element.autofocus!==true){//autofocus在支持的浏览器中是true,不支持的是空字符串element.focus();}});
//change事件常用于验证用户在字段中输入的数据var textbox=document.forms[0].elements[0];EventUtil.addHandler(textbox,'focus',function(event){event=EventUtil.getEvent(event);var target=EventUtil.getTarget(event);if(target.style.backgroundColor!='red'){target.style.backgroundColor='yellow';}});EventUtil.addHandler(textbox,'blur',function(event){event=EventUtil.getEvent(event);var target=EventUtil.getTarget(event);if(/[^\d]/.test(target.value)){target.style.backgroundColor='red';}else{target.style.backgroundColor='';}});EventUtil.addHandler(textbox,'change',function(event){event=EventUtil.getEvent(event);var target=EventUtil.getTarget(event);if(/[^\d]/.test(target.value)){target.style.backgroundColor='red';}else{target.style.backgroundColor='';}});



【文本框脚本】

//选择文本select(),无参。//应用:让用户在文本框获得焦点时选择所有文本,不必一个一个删除。//IE9+、Opera、Firefox、Chrome、Safari,只有用户选择且释放鼠标才触发select事件;//IE8及以前,只要选择一个字符,不释放鼠标,就触发;//调用select()会触发select事件;//HTML5新增selectionStart和selectionEnd属性//IE9+、Opera、Firefox、Chrome、Safari//IE8及以前用document.selection对象,保存着用户在整个文档范围选择的文本信息function getSelectedText(textbox){if(typeof textbox.selectionStart=='number'){return textbox.value.substring(textbox.selectionStart,textbox.selectionEnd);}else if(document.selection){return document.selection.createRange().text;}}//HTML5选择部分文本:setSelectionRange(),两个参数,起始结束索引//IE9+、Opera、Firefox、Chrome、Safari//IE8及以前用范围选择文本function selectText(textbox,startIndex,stopIndex){if(textbox.setSelectionRange){textbox.setSelectionRange(startIndex,stopIndex);}else if(textbox.createTextRange){var range=textbox.createTextRange();range.collapse(true);//折叠范围,true表示折叠刀范围起点range.moveStart('character',startIndex);range.moveEnd('character',stopIndex-startIndex);range.select();}textbox.focus();}textbox.value='hello world!';selectText(textbox,0,textbox.value.length);
//过滤输入屏蔽字符//在Firefox中所有由非字符键触发的keypress事件对应字符编码0,Safari3以前为8EventUtil.addHandler(textbox,'keypress',function(event){event=EventUtil.getEvent(event);var target=EventUtil.getTarget(event);var charCode=EventUtil.getCharCode(event);if(!/\d/.test(String.fromCharCode(charCode))&&charCode>9&&!event.ctrlKey){EventUtil.preventDefault(event);}});
//剪切板事件://beforecopy、copy、beforecut、cut、beforepaste、paste//在Safari、Chrome、Firefox中三个before事件只会显示针对文本框的上下文菜单的情况触发,//IE会在触发copy、cut、paste之前先行触发before。////通过before可以向剪贴板发送数据,或者从剪贴板取得之前修改数据,//访问数据用clipboardData对象,IE中是window的属性,Firefox4+、Safari、Chrome中是event的属性,//在Firefox、Safari、Chrome中只有在处理剪贴板事件期间这个对象才有效,IE中可随时访问。////clipboardData的三个方法:getData()、setData()、clearData()//在Firefox、Safari、Chrome中只允许在onpaste事件处理程序中访问getData()////补充:可以在paste事件中确认剪贴板中的值是否有效,若无效可取消默认行为var EventUtil={//...getClipboardText:function(event){var clipboardData=(event.clipboardData||window.clipboardData);return clipboardData.getData('text');},setClipboardText:function(event){if(event.clipboardData){return event.clipboardData.setData('text/plain',value);}else if(window.clipboardData){return window.clipboardData.setData('text',value);}},//...};
//自动切换焦点//在前一个文本框字符数达到最大后,自动切换焦点到下一个文本框(function(){function tabForward(event){event=EventUtil.getEvent(event);var target=EventUtil.getTarget(event);if(target.value.length==target.maxLength){var form=target.form;for (var i = 0,len=form.elements.length; i < len; i++){if(form.elements[i]==target){if(form.elements[i+1]){form.elements[i+1].focus();}return;}}}}var textbox1=document.getElementById('txtTel1');var textbox2=document.getElementById('txtTel2');var textbox3=document.getElementById('txtTel3');EventUtil.addHandler(textbox1,'keyup',tabForward);EventUtil.addHandler(textbox2,'keyup',tabForward);EventUtil.addHandler(textbox3,'keyup',tabForward);//keyup会在用户输入了新字符后出发,此时是检测内容长度最佳时机})();



【选择框脚本】


//取得所有选中项//遍历选项集合,然后测试每个选项的selected属性function getSelectedOptions(selectbox){var result=new Array();var option=null;for (var i = 0,len=selectbox.options.length; i < len; i++) {option=selectbox.options[i];if(option.selected){result.push(option);}}return result;}
//动态创建选项的三种方法://1、DOM方法var selectbox=document.forms[0].elements['location'];var newOption=document.createElement('option');newOption.appendChild(document.createTextNode('Option text'));newOption.setAttribute('value','Option value');selectbox.appendChild(newOption);//2、使用Option构造函数//IE中存在bug,不能正确设置新选项的文本var newOption=new Option('Option text','Option value');selectbox.appendChild(newOption);//3、使用选择框的add(newOpt,relOpt)方法//该方法在relOpt之前插入newOpt,若要插入到最后,应将relOpt设为null,//IE中第二个参数可选,但必须是新选项之后选项的索引,//兼容DOM的浏览器要求必须指定第二个参数,//所以,//将relOpt设为undefined,兼容所有浏览器插入到最后//(插入其他位置用DOM+insertBefore()方法)var newOption=new Option('Option text','Option value');selectbox.add(newOption,undefined);
//移除选项的三种方式://1、DOM的removeChild()方法selectbox.removeChild(selectbox.options[0]);//2、使用选择框的remove()方法selectbox.remove(0);//3、将相应选项设为nullselectbox.options[0]=null;
//移动和重排选项//将第一个选择框中的第一个选项移动到第二个选择框var selectbox1=document.getElementById('selLocations1');var selectbox2=document.getElementById('selLocations2');selectbox2.appendChild(selectbox1.options[0]);//在选择框中向前移动一个选项的位置var optionToMove=selectbox.options[1];selectbox.insertBefore(optionToMove,selectbox.options[optionToMove.index-1]);//在选择框中向后移动一个选项的位置var optionToMove=selectbox.options[1];selectbox.insertBefore(optionToMove,selectbox.options[optionToMove.index+2]);//注:IE7存在页面重绘问题,有时用DOM方法重排的选项不能马上正确显示


【表单序列化】


function serialize(form){var parts=[],field=null,i,len,j,optLen,option,optValue;for(i = 0,len=form.elements.length; i < len; i++) {field=form.elements[i];switch(field.type){//type属性未定义的不需要序列化case "select-one":case "selsct-multiple":if(field.name.length){for(j=0,optLen=field.options.length;j<optLen;j++){option=field.options[j];if(option.selected){optValue='';if(option.hasAttribute){//兼容DOM的浏览器中optValue=(option.hasAttribute('value')?option.value:option.text);//如果不存在value特性,或存在但为空字符串,用选项的文本来代替}else{//IEoptValue=(option.attributes['value'].specified?option.value:option.text);}parts.push(encodeURIComponet(field.name)+'='+encodeURIComponet(optValue));}}}break;case undefined:case "file":case "submit":case "reset":case "button":break;case "radio":case "checkbox":if(!field.checked){break;}default://不包含没有名字的表单字段if(field.name.length){parts.push(encodeURIComponet(field.name)+'='+encodeURIComponet(optValue));}}}return parts.join("&");}


原创粉丝点击