继续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