继续DOM的研究工作,我们扩展对dom api的学习!
1.介绍针对低级浏览器,能力的监测处理:
2.针对移动端,touch事件的介绍:
3.最后做几个网页实例!
4.ajax的介绍:ajax输出json格式文件 jsonp的介绍 xhr2的介绍
http://www.w3school.com.cn/ajax/ajax_xmlhttprequest_create.asp
5.cookie的介绍:设置cookie和删除cookie
6.html5 存储的介绍:web客户端存储(localStorage sessionsStorage) 缓存( cache manifest 文件)
7.html5中新元素如canvas,video、audio的api简单介绍
http://www.w3school.com.cn/tags/html_ref_audio_video_dom.asp
http://www.w3school.com.cn/tags/html_ref_canvas.asp
8.html设备支持的接口介绍:webaudio
9.其他dom接口相关介绍:
一、dom能力监测处理
对于ie,我们是十分痛恨的,布局的时候,为了兼容低级ie或者特殊浏览器布局我们要做hack处理,
同样,js也是如此,我们介绍的都是满足w3c的dom api,针对低级ie还有特殊浏览我们要做兼容处理,因为运用标准的api是不支持的,好在不支持的都有替代api,我们就可以做兼容处理了!
事件中事件对象 event 的处理
html
<div id="fu">123</div>
js
window.onload=function(){ var fu=document.getElementById("fu"); fu.onclick=function(event){ alert(event.type); }; };
在高级浏览器,点击弹出 click
通过ie6打开发现毫无反应:针对event对象,低级ie把event最为window的event属性返回去调用
兼容处理代码
var event=event||window.event; 高级浏览器最后得到event对象,低级浏览器不支持此调用,采用或后面的代码
js的或处理,采用真假判断机制,如果或前面为真,有内容,被采用,后面被忽略:
测试代码:
window.onload=function(){ var aa=null; var bb=123; var cc=aa||bb; alert(cc); var aa2=222; var bb2=333; var cc2=aa2||bb2; alert(cc2); };
第一次alert出123,因为aa为空,采用后面,第二次输出222,因为aa2为真,有内容,后面被忽略
var event=event||window.event;
加入event能力检测代码实现:
window.onload=function(){ var fu=document.getElementById("fu"); fu.onclick=function(event){ var event=event||window.event; alert(event.type); }; };
完美输出,针对低级ie,我们这次不输出 event的type,而是去输出event.target去试一试
这这属性将返回触发事件的最小元素,我们输出他的innerHTML测试
window.onload=function(){ var fu=document.getElementById("fu"); fu.onclick=function(event){ var event=event||window.event; alert(event.target.innerHTML); }; };
我只是做了最简单测试,就一个元素,弹出的当然就是里面的123,我们低级ie测试无翻译,看来
event.target不被支持了,
2.事件中事件对象 event.target 的处理
对于低级ie已经无奈,我们看对他的处理办法
var target=event.target||event.srcElement
测试代码:
window.onload=function(){ var fu=document.getElementById("fu"); fu.onclick=function(event){ var event=event||window.event; var target=event.target||event.srcElement alert(target.innerHTML); }; };
ok了,继续工作,我们不以直接添加事件的方式处理,通过监听事件方法:
js代码修改
window.onload=function(){ var fu=document.getElementById("fu"); fu.addEventListener("click",function(event){ var event=event||window.event; var target=event.target||event.srcElement; alert(target.innerHTML); },false); };
高级浏览器,监听事件还是没问题的,测试低级ie,大哥还是失灵
还要兼容,低级ie的事件监听方法是:
object.attachEvent(on+type,function);
w3c是:
object.addEventListener(type,function,useCapture);
这次用||在处理一次,好吧,哭着也不行了,我们通过函数的封装来一次兼容处理
window.onload=function(){ var fu=document.getElementById("fu"); objeventadd(fu,"click",function(){ var event=event||window.event; var target=event.target||event.srcElement; alert(target.innerHTML); }); function objeventadd(obj,ev,fn){ if(obj.addEventListener){ obj.addEventListener(ev,fn,false); }else if(obj.attachEvent){ obj.attachEvent("on"+ev,fn); }; }; };
一个封装函数,加上if处理,我们也发现那个货处理其实全部通过if也可以的,不过能用||就用这个,代码简洁重要,总结处理代码:
function objeventadd(obj,ev,fn){
if(obj.addEventListener){
obj.addEventListener(ev,fn,false);
}else if(obj.attachEvent){
obj.attachEvent("on"+ev,fn);
};
};
最重要的兼容算是解决了,我们看其他兼容问题:下面的我就直接列举了
3.事件对象相对页面坐标位置兼容:
var evx=event.pageX||event.x
var evy=event.pageY||event.y
获取事件对象,相对页面的左侧坐标和顶部坐标
event.clientX ,event.clientY 没有兼容问题
除了相对页面的坐标,还可以获取相对添加事件元素的坐标
event.layerX 事件对象相对元素的坐标
event.layerY
4.事件对象阻止冒泡和默认行为兼容:
组织冒泡
event.stopPropagation(); w3c
event.cancelBubble = true; 低级ie
阻止默认
event.preventDefault(); w3c
event.returnValue = false; 低级ie
5.滚轮事件onmousewheel兼容:
obj.onmousewheel = function(event) {
var event=event||window.event;
}; 除了火狐以为
obj.addEventListener("DOMMouseScroll", function(event) {
var event=event||window.event;
}); 火狐
鼠标滚轮就是中间轮的事件
大部分的兼容处理都已经介绍完了,为了下面的手机touch事件,我们提前做一个组合事件的封装处理:
依据鼠标按下,移动,抬起,我们组合判断鼠标是向那个方向移动了!
原理:三个事件都可以获取相对页面的恶坐标,我们把抬起是的坐标与按下坐标比较,就可以得出鼠标一次组合行为的方向,一次行为,还是要用到为0和为1的判断,与前面例子的拖拽登录框类似:
鼠标按下抬起放下判断实例:
js:
window.onload=function(){ var pape=document.documentElement; var isd=0; var downx=null; var downy=null; pape.onmousedown=function(event){ isd=1; downx=event.clientX; downy=event.clientY; }; pape.onmousemove=function(event){ if(isd==1){isd=1; }else{}; }; pape.onmouseup=function(event){ if(isd==1){ var X = event.clientX - downx; var Y = event.clientY - downy; if ( Math.abs(X) > Math.abs(Y) && X > 0 ) { alert("右"); } else if ( Math.abs(X) > Math.abs(Y) && X < 0 ) { alert("左"); } else if ( Math.abs(Y) > Math.abs(X) && Y > 0) { alert("下"); } else if ( Math.abs(Y) > Math.abs(X) && Y < 0 ) { alert("上"); } else{ alert("原位"); }; isd=0; }else{}; }; };
相关:Math.abs(num) 获取绝对值,参数是数字
我们执行js,可以判断鼠标在页面的从按下到抬起的方向!
二、移动端Touch事件
基本touch事件:
touchstart 触摸开始,按下
touchmove 触摸移动
touchend 触摸离开
触摸事件与我们mouse三事件正好吻合,同样,手机上没有over这些特殊事件,我们常用的也就是这三个,我们看事件监听方式:
1.直接添加;
obj.ontouchstart =function(event){}
obj.ontouchmove =function(event){}
obj.ontouchend =function(event){}
2.方法添加,即监听添加,应为移动端都是高级浏览器,webkit内核,不用考虑低级ie的兼容问题
obj.addEventListener("touchstart ", function(event) { });
obj.addEventListener("touchmove ", function(event) { });
obj.addEventListener("touchend ", function(event) { });
和我们以前写法一样的,不过是这次用移动事件的名字而已
我们要注意的是,触摸事件的event对象所附有的一些属性已经不同于pc事件,我们列举出来:
touch事件的新属性 已有对应的正常属性
event.targetTouches 得到出发事件的手指集合(最小元素) event 得到触发事件的对象
event.targetTouches[0] .pageX 一个手指相对页面的位置 event.pageX 事件相对页面的位置
event.touches 获取所有touch事件触发对象,touch不同于click这些事件,鼠标事件只能有一个,touch会有多个,一个屏幕可以放几个手指
event.Touches[0] .pageX
我们知道,手指放在手机上,回不经意出发很多默认行为,我们为了js好的执行,需要调用时,阻止默认行为:
event.preventDefault(); 和正常相同
我们修改上面案例代码也就可以检测触摸方向了!
三、实战开发
学了这么多dom的接口,我们需要做一些例子了
1.全屏漂浮广告: (属性处理)
改变广告标签的left和top样式
需要接口:
setInterval() clearInterval() 间隔处理,不断修改left和top实现移动
ele.offsetLeft ele.offsetTop 获取当前位置的eeft和top
ele.style.left ele.style.top 对left和top做修改赋值
if(){}else{} 边界判断,不能超出屏幕
function name(){} 配合间隔函数的函数定义
document.documentElement.clientHeight document.documentElement.clientWidth 获取页面宽高,做衡量值
html:
<div id="fu" style="position:absolute; left:0px;top:0px; background:#ffa;width:200px;height:200px; ">123</div> <p style="height:1500px;"></p>
js:
window.onload=function(){ var fu=document.getElementById("fu"); var hengw=document.documentElement.clientWidth-200; var hengh=document.documentElement.clientHeight-200; var zx=1; var zy=1; var dong=setInterval(function(){ var eley=fu.offsetTop; var elex=fu.offsetLeft; eley=eley+zx*1; elex=elex+zy*1; if(eley>hengh){zx=-1;}; if(eley<0){zx=1;}; if(elex>hengw){zy=-1;}; if(elex<0){zy=1;}; fu.style.top=eley+"px"; fu.style.left=elex+"px"; },10); fu.onmouseover=function(){ clearInterval(dong); }; fu.onmouseout=function(){ dong=setInterval(function(){ var eley=fu.offsetTop; var elex=fu.offsetLeft; eley=eley+zx*1; elex=elex+zy*1; if(eley>hengh){zx=-1;}; if(eley<0){zx=1;}; if(elex>hengw){zy=-1;}; if(elex<0){zy=1;}; fu.style.top=eley+"px"; fu.style.left=elex+"px"; },10); }; }
广告自动移动,鼠标放停止,离开继续移动,
eley=eley+zx*1;
我们为什么要这样处理,我们知道在达到边界做出的处理就是元素的属性由+变成-变化值;
主要原理:a+b 和a-b 互相转化,a是基础值, b的变化值,我们做出a+(c)b;z=1、z=-1;用可变化的c做处理
2.下拉框左右选项移动: (节点操作)
原理:我们是把一侧selsect下选中的option插入到另一侧select下,选中的option具有selected属性,判断是否有这个属性,有的我们就插入到另一侧,select设置multiple属性,可多选,插入有可能插入多个,每次都要从头遍历一次去判断哪个要被插入;
需要接口:
id获取selset
tagname获取下面的恶optoon
for(){}遍历处理
if(){}else{}判断处理
ele.selected 检测元素的selected属性
ele.appendChild() 插入子节点
html:
<select id="left" style="width:100px;" size="5" multiple> <option>11111</option> <option>22222</option> <option>333333</option> <option>4444444</option> <option>5555555</option> </select> <span id="movel">右移动</span> <span id="mover">左移动</span> <select id="right" style="width:100px;" size="5" multiple> </select>
js:
window.onload=function(){ var left=document.getElementById("left"); var right=document.getElementById("right"); var leftoptions=left.getElementsByTagName("option") var rightoptions=right.getElementsByTagName("option") var movel=document.getElementById("movel"); var mover=document.getElementById("mover"); movel.onclick=function(){ var arrl=[]; for(var i=0;i<leftoptions.length;i++){ if(leftoptions[i].selected){ arrl.push(leftoptions[i]); }; }; for(var i=0;i<arrl.length;i++){ right.appendChild(arrl[i]); }; }; mover.onclick=function(){ var arrr=[]; for(var i=0;i<rightoptions.length;i++){ if(rightoptions[i].selected){ arrr.push(rightoptions[i]); }; }; for(var i=0;i<arrr.length;i++){ left.appendChild(arrr[i]); }; }; }
相关知识:arr.push(node) 数组的插入方法,官方叫进栈,就是把node插入到一个数组中,保存
按住ctrl+点击选项,可移动多个
3.封装处理 (dom优化)
通过类名查找的封装
每次都要给标签添加id去查找,这很不符合我们的习惯,有人多可以用querySelectorAll(),这个不就可以了,和jq的选择器差不多了,主要是不兼容低级ie
我们打算找到指定类名,去处理它,就像这样:selectclassname返回节点,好了我们就用这个名字去封装这个方法
一个html页面会有很多的标签:div span a等,还会各种件套,同样很多不一样的标签会有同样的类名
我们罗列出相关的api:
document.getElementsByTagName("*") 可以返回所有的标签
node.className 可以获取标签的类名
这好像可以了,我们想象一下,封装一个函数,以查找的类名做参数,内部对所有标签进行遍历,加上对类名的判断是否等于参数的值,创建一个数组,把等于参数值得标签插入进去,最后返回!
相关接口:
for(){}
if(){}
arr.push() 插入到数组中
return obj 返回一个值
封装好的函数:
function selectclassname(classname){
var allnode=document.getElementsByTagName("*");
var classnode=[];
for(var i=0;i<allnode.length;i++){
if(allnode[i].className==classname){
classnode.push(allnode[i]);
};
};
return classnode;
};
我们既然写了,就得做点东西演示一下,
html:
div class="aa">1</div> <div class="aa">1</div> <div class="bb">1</div> <div class="aa">1</div>
js:
window.onload=function(){ function selectclassname(classname){ var allnode=document.getElementsByTagName("*"); var classnode=[]; for(var i=0;i<allnode.length;i++){ if(allnode[i].className==classname){ classnode.push(allnode[i]); }; }; return classnode; }; var aa=selectclassname("aa"); for(var i=0;i<aa.length;i++){ aa[i].innerHTML="woshi"+i; }; }
还行,实现了每个赋值
自身删除的封装
removeChild() 删除字节点 node. removeChild(selnode)
删除的操作是找到一个元素,在确定他下面一个子元素,然后删除,现在我们找一一个元素,把自身删除
我们可以通过parentnode得到当前元素父元素,然后在调用删除方法,这时候参数就是本元素了,
方法名就是remove()
function remove(node){
node.parentNode.removeChild(node);
};
html:
<div id="aa">1</div>
js:
window.onload=function(){ function remove(node){ node.parentNode.removeChild(node); }; var aa=document.getElementById("aa"); remove(aa); }
4.全选,取消全选
全选操作是对复选框的处理,其实就是对input的chenked属性的设置和取消
html:
<br> <input type="checkbox" id="all"> 全选 <br><br> <div style="width:200px; border:1px solid #000;" id="box"> <input type="checkbox"> 1<br><br> <input type="checkbox"> 2<br><br> <input type="checkbox"> 3<br><br> <input type="checkbox"> 4<br><br> <input type="checkbox"> 5<br><br> <input type="checkbox"> 6<br><br> <input type="checkbox"> 7<br><br> </div>
js:
window.onload=function(){ var all=document.getElementById("all"); var box=document.getElementById("box"); var boxlists=document.getElementsByTagName("input"); all.onchange=function(){ //alert(all.checked) if(all.checked){ for(var i=0;i<boxlists.length;i++){ boxlists[i].checked=true; }; }else{ for(var i=0;i<boxlists.length;i++){ boxlists[i].checked=false; }; }; }; }
5.焦点图实例
因为有很多的css样式,我就粘贴整部分代码了
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>爱</title> <style type="text/css"> *{ padding:0; margin:0} html,body{ height: 100%; width: 100%;} #box{ width: 228px; height: 229px; overflow: hidden;} #box a{display: none;} #box a.b{display:block;} .ddd{ position: relative;width: 228px; height: 229px;} #an{ position: absolute; bottom: 0px; left: 0; background-color: #daa;} #an span{ padding: 0 5px; cursor: pointer;} #an span.se{color:#fff;} #newc{height: 30px;line-height: 30px;width: 228px;overflow: hidden;} #newc span{display: none;height: 30px;} #newc span.c{display:block;} </style> </head> <body> <div class="ddd"> <div id="box"> <a href="" class="b">第1个图</a> <a href="" >第2个图</a> <a href="" >第3个图</a> <a href="" >第4个图</a> <a href="" >第5个图</a> </div> <div id="an"> <span class="se">1</span> <span>2</span> <span>3</span> <span>4</span> <span>5</span> </div> <div id="newc"> <span class="c">111111111111</span> <span>22222222222</span> <span>33333333333333</span> <span>44444444444444</span> <span>5555555555555</span> </div> </div> </body> <script type="text/javascript"> window.onload=function(){ //动画自动播放 var oImg=document.getElementById('box').getElementsByTagName('a'); var i=0; var j=0; var k=0; var dong=setInterval(dongc,1500); function dongc(){ k++ if(k>=oImg.length) {k=-1;} else{for(j=0;j<oImg.length;j++) {if(oImg[j]==oImg[k]) {oImg[j].className="b" oSpan[j].className="se" newc[j].className="c" } else{oImg[j].className="" oSpan[j].className="" newc[j].className=""}}}} //鼠标放在数字上面 var oSpan=document.getElementById('an').getElementsByTagName('span'); var newc=document.getElementById('newc').getElementsByTagName('span'); for(i=0;i<oSpan.length;i++) {oSpan[i].onmouseover=function(){ clearInterval(dong); for(i=0;i<oSpan.length;i++) {if(oSpan[i]==this) {oImg[i].className="b" oSpan[i].className="se" newc[i].className="c" return i} else{oImg[i].className="" oSpan[i].className="" newc[i].className=""}}} oSpan[i].onmouseout=function(){ oSpan[i].className="" newc[i].className="c" k=i; dong=setInterval(dongc,1500);}} //结束了 } </script> </html>
6.隔行换色
主要是对tabel的处理,就是基数的tr一个颜色,偶数的一个颜色非常简单的处理代码
html:
<table id="tab"> <tr><td>111</td></tr> <tr><td>222</td></tr> <tr><td>333</td></tr> <tr><td>444</td></tr> <tr><td>555</td></tr> </table>
js:
window.onload=function(){ var tab=document.getElementById("tab"); var tr=tab.getElementsByTagName("tr"); for(var i=0;i<tr.length;i++){ if(i%2==0){ tr[i].style.background="#ffa"; }else{ tr[i].style.background="#ccc"; }; }; }
相关知识: 10%2 获取 10除以2的余数,余数是0,商是5
总结:
到了最后,我们发现例子都非常简单,一是为了学dom,二就是我们还没有进入js的核心就是是语法es的学习,
我们不能借用太多js语法做复杂处理东西,js语法es的相关使用:
var xx 创建变量
array 数组的使用,还有push() 插入数据
alert() 方法
function 的使用
for 循环
if 判断
间隔函数 setInterval
Math对象 数学工具对象的abs()方法,返回绝对值
逻辑处理 或 ||
求余数 %
布尔类型 true 和false
这一部分就到这里了,目录扩展的1,2,3就结束了,以后的内容会在后面介绍到
开源实例,大家可以多多了解js 的处理:
http://www.oschina.net/code/snippet_2352644_49815
http://www.oschina.net/code/snippet_2352644_49974