JavaScript学习笔记(二)
DOM基础概念、操作
DOM概念
DOM 是 W3C(万维网联盟)的标准。
DOM 定义了访问 HTML 和 XML 文档的标准:
W3C 文档对象模型 (DOM) 是中立于平台和语言的接口,它允许程序和脚本动态地访问和更新文档的内容、结构和样式。
W3C DOM 标准被分为 3 个不同的部分:
核心 DOM - 针对任何结构化文档的标准模型
XML DOM - 针对 XML 文档的标准模型
HTML DOM - 针对 HTML 文档的标准模型
HTML DOM 是:
HTML 的标准对象模型
HTML 的标准编程接口
W3C 标准
HTML DOM 定义了所有 HTML 元素的对象和属性,以及访问它们的方法。
换言之,HTML DOM 是关于如何获取、修改、添加或删除 HTML 元素的标准。
根据 W3C 的 HTML DOM 标准,HTML 文档中的所有内容都是节点(一共12种类型):
-
整个文档是一个文档节点
-
每个 HTML 元素是元素节点:1
-
HTML 元素内的文本是文本节点:3
-
每个 HTML 属性是属性节点:2
-
注释是注释节点
DOM会把文档看作是一棵树,同时定义了很多方法(下面例子)来操作这棵数中的每一个元素(节点)
ex.
- getElementById
- getElementByTagName
- document
- document.body
- childNodes、children、nodeType、attributes
childNodes、children、nodeType、attributes
obj.childNodes : 只读属性 子节点列表集合(兼容性不好)
标准下:包含了文本和元素类型的节点,也会包含非法嵌套的子节点
非标准下:只包含元素类型的节点,ie7以下不会包含非法嵌套子节点
childNodes只包含一级子节点,不包含后辈孙级以下的节点
obj.nodeType : 只读属性 当前元素的节点类型
obj.attributes : 只读属性 属性列表集合
obj.children : 只读属性 子节点列表集合(和childNodes基本一样,兼容性更好)
标准下:只包含元素类型的节点
非标准下:只包含元素类型的节点
firstChild、lastChild、NextSibling、previousSibling
obj.firstChild : 只读属性 第一个子节点
标准下:firstChild会包含文本类型的节点
非标准下:只包含元素节点
obj.firstElementChild : 只读属性 标准下获取第一个元素类型的子节点(非标准ie没有这个属性)
兼容性解决:
var oFirst = oUl.firstElementChild || oUl.firstChild;
oFirst.style.background = 'red';
其他同理
obj.lastChild || obj.lastElementChild 最后一个子节点
obj.nextSibling || obj.nextElementSibling 下一个兄弟节点
obj.previousSibling || obj.previousElementSibling 上一个兄弟节点
用上面的方法时,当没有子节点时会出错
因为oUl.firstElementChild没有读取到元素节点返回null即false,然后读到|| 后的oUl.firstChild,会读取到本文节点(换行符/br),本文节点没有style等属性
解决办法:
if ( oUl.children[0] ) {
oUl.children[0].style.background = 'red';
} else {
alert( '没有子节点可以设置' );
}
parentNode、offsetParent
obj.parentNode : 只读属性 当前节点的父级节点
obj.offsetParent : 只读属性 离当前元素最近的一个有定位属性的父节点
如果没有定位父级,默认是body
ie7以下,如果当前元素没有定位默认是body,如果有定位则是html
ie7以下,如果当前元素的某个父级触发了layout(像zoom: 1;),那么offsetParent 就会被指向到这个触发了layout特性的父节点上
offsetLeft、offsetTop、clientWidth、offsetWidth
obj.offsetLeft/Top : 只读 属性 当前元素到定位父级的距离(偏移值)
即到当前元素的offsetParent的距离
如果没有定位父级
offsetParent -> body
offsetLeft -> html
如果有定位父级
ie7以下:如果自己没有定位,那么offsetLeft[Top]是到body的距离
如果自己有定位,那么就是到定位父级的距离
其他:到定位父级的距离
style.width,clientWidth,offsetWidth区别
style.width : 样式宽
clientWidth : 可视区宽
offsetWidth : 占位宽
<div id="div1" style="width: 100px; height: 100px; border: 1px solid red; padding: 10px; margin: 10px;"></div>
var oDiv = document.getElementById('div1');
alert( oDiv.style.width ); //100px 带单位,下面两个不带单位的
alert( oDiv.clientWidth ); //样式宽 + padding 120
alert( oDiv.offsetWidth ); //样式宽 + padding + border 可视区宽 + 边框 122
小技巧:
想获取某元素到HTML的距离时,但它上面的一个或多个父级有定位,可以通过offsetParent和offsetTop/Left配合获取:(一层一层往上推)
var iTop = 0;
var obj = oDiv3;
while (obj) {
iTop += obj.offsetTop;//得到和上一个定位父级的距离,如果没有定位父级就直接是到HTML的距离
obj = obj.offsetParent;//得到上一个定位父级的元素,一直到body,body.offsetTop为0; body的父级为null不存在,循环停止
}
可以封装成函数使用;
getAttribute()、setAttribute()、removeAttribute()
obj.getAttribute(属性名称); 方法 获取指定元素的指定属性的值
用.和[]的形式无法操作元素的自定义属性,getAttribute可以操作元素的自定义属性,可以获取元素属性实际的值,但ie7下还是会返回资源的绝对路径
ex.
alert( oImg.src ); //输出绝对路径
alert( oImg.getAttribute('src') ); //输出相对路径
obj.setAttribute(属性名称,属性值); 方法 给指定元素指定的属性设置值
obj.removeAttribute(属性名称); 方法 移除指定的元素的指定的属性
createElement()、removeChild()、appendChild()、insertBefore()、replaceChild()
**document.createElement(标签名称); ** 方法 创建元素
创建了但是在js里没有加到HTML中,要用appendChild()、insertBefore()、replaceChild() 等方法添加
**obj.removeChild(要删除的元素); ** 方法 删除元素
**obj.appendChild(要添加的元素); ** 方法 追加子元素
obj.insertBefore(新的元素,被插入的元素); 方法 在指定元素前面插入一个新元素
在ie下如果第二个参数的节点不存在,会报错
在其他标准浏览器下如果第二个参数的节点不存在,则会以appendChild的形式进行添加
兼容性解决
if ( oUl.children[0] ) {
oUl.insertBefore( 新的元素, oUl.children[0] );
} else {
oUl.appendChild( 新的元素 );
}
obj.replaceChild(替换节点,被替换节点); 方法 替换子节点
appendChild,insertBefore,replaceChild都可以操作动态创建出来的节点,也可以操作已有节点,都类似于剪切,操作后原有的节点会没有了
class的操作 getElementsByClassName()、addClass()、removeClass()
getElementsByClassName()和getELementById()的用法一样
addClass()和removeClass()是属于自己封装的函数,类似于jQuery ;
addClass()
function addClass(obj,className){
//如果原来没有class
if (obj.className == '') {
obj.className = className;
}else{
//如果原来有class
var arrClassName = obj.className.split(' ');//以空格拆分成数组
var _index = arrIndexOf(arrClassName,className);
if (_index != -1) {
//如果要添加的class在原来的class中不存在
obj.className += ' ' + className;
}
//如果要添加的class在原来的class中存在,则不用添加
}
//通过这个函数可以找到arr数组中有没有v的存在并返回它的位置
function arrIndexOf(arr,v){
for (var i = 0; i < arr.length; i++) {
if (arr[i] == v) {
return i;
}
}
return -1;
}
}
removeClass()
function removeClass(obj,className){
//如果原来有class
if(obj.className != ''){
var arrClassName = obj.className.split(' ');//以空格拆分成数组
var _index = arrIndexOf(arrClassName,className);
//如果有要移除的class
if(_index != -1){
arrClassName.splice(_index,1);
obj.className = arrClassName.join(' ');//用空格拼接成字符串
}
}
//如果原来没有class,不用删除
//通过这个函数可以找到arr数组中有没有v的存在并返回它的位置
function arrIndexOf(arr,v){
for (var i = 0; i < arr.length; i++) {
if (arr[i] == v) {
return i;
}
}
return -1;
}
}
表单
表格操作
tHead: 表格头
tBodies: 表格正文
tFoot: 表格尾
rows:行
cells:列
obj.tBodies[0].rows[1].cells[1].innerHTML
obj.tBodies[0].rows[1].cells[1].innerHTML
可以直接这样操作 第0个body的第一行第一列可以直接这样操作 第0个body的第一行第一列
<table border="1">
<thead> //<thead> 内部必须拥有 <tr> 标签!
<tr>
<th>Month</th>
<th>Savings</th>
</tr>
</thead>
<tfoot>
<tr>
<td>Sum</td>
<td>$180</td>
</tr>
</tfoot>
<tbody>
<tr>
<td>January</td>
<td>$100</td>
</tr>
<tr>
<td>February</td>
<td>$80</td>
</tr>
</tbody>
</table>
表单操作
formObj.name 获取表单中一个元素
ex.
var oForm = document.getElementById('form1');
alert( oForm.username.value );
<form id="form1">
<input type="text" id="text1" name="username" value="" />
</form>
onchange : 事件 当值发生改变的时候触发
ex.
oDiv.onchange = function() {
...
};
input中
text : 当光标离开元素的时候再去判断值是否发生了变化,如果发生了变化则触发 onchange事件
radio /checkbox :
标准下只要值改变了就会触发
非标准下要焦点离开了时值改变了才会触发
select : 当值发生改变的时候触发
表单事件 onsubmit、submit()、onreset、confirm()
onsubmit : 事件 当提交表单时触发
submit() : 方法 提交表单
onreset : 事件 当重置表单时触发
confirm() : 方法 确定对话框
BOM
BOM概念、操作open()、close()
BOM是browser object model的缩写,简称浏览器对象模型
BOM提供了独立于内容而与浏览器窗口进行交互的对象
由于BOM主要用于管理窗口与窗口之间的通讯,因此其核心对象是window
BOM由一系列相关的对象构成,并且每个对象都提供了很多方法与属性
BOM缺乏标准,JavaScript语法的标准化组织是ECMA,DOM的标准化组织是W3C
BOM最初是Netscape浏览器标准的一部分
open(地址默认是空白页面,打开方式默认新窗口) 方法 打开一个新窗口
返回值 返回的新开页面的window对象,后面还有两个参数,但不常用且兼容性不好
ex.
window.open('http://www.baidu.com', '_self');
不要混淆方法 Window.open() 与方法 Document.open(),这两者的功能完全不同。
为了使您的代码清楚明白,请使用 Window.open(),而不要使用 open()。
close() 方法 关闭一个窗口
关闭哪个窗口由前面的值决定
ex.
window.close(); //关闭当前窗口
opener = window.open(); //返回值 返回的新开页面的window对象
opener.close(); //可以通过关闭用window.open方法打开的窗口
兼容性不好
ff : 无法关闭
chrome : 直接关闭
ie : 询问用户
BOM属性
window.navigator.userAgent 浏览器信息
用来判断浏览器类型
ex.
if ( window.navigator.userAgent.indexOf('MSIE') != -1 ) {
alert('我是ie');
} else {
alert('我不是ie');
}
**window.location **: 浏览器(地址栏)地址信息
window.location.href 等于window.location内容 即浏览器(地址栏)地址信息
window.location.search 等于url?后面的内容
window.location.hash 等于url#后面的内容
文档宽高及窗口事件
可视区尺寸
document.documentElement.clientHeight
第一个document指文档对象,对象是没有尺寸的
第二个指文档元素,元素才由宽高
document.documentElement指文档对象下的文档元素
滚动距离scrollTop/Left(可视区顶部到整个页面顶部的距离)
document.documentElement.scrollTop/Left
可读可写,赋值时不用带单位
chrome中认为滚动条并不是属于文档元素的,而是body的
其他浏览器认为是属于文档的
兼容性解决
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
内容实际宽高 obj.scrollHeight
指盒子实际的大小
文档高度 document.documentElement.offsetHeight
ie : 如果内容没有可视区高,那么文档高就是可视区,有兼容性问题
兼容性解决
在去掉body的margin和padding时,文档元素的高和body的高没有区别
document.body.offsetHeight
onscroll 事件 当滚动条滚动的时候触发
**onresize ** 事件 当窗口大小发生变化的时候触发
不是移动一像素触发一次,而是以时间进行运算的,在一个时间间隔内有变化时就触发一次
事件详解
焦点事件 onfocus、onblur
**焦点 **: 使浏览器能够区分用户输入的对象,当一个元素有焦点的时候,那么他就可以接收用户的输入。
我们可以通过一些方式给元素设置焦点
- 点击
- tab键
- js
不是所有元素都能够接收焦点的,能够响应用户操作的元素才有焦点
onfocus 事件 当元素获取到焦点的时候触发
**onblur ** 事件 当元素失去焦点的时候触发
obj.focus() 方法 给指定的元素设置焦点
obj.blur() 方法 取消指定元素的焦点
**obj.select() ** 方法 选择(全选)指定元素里面的文本内容
这三个方法都是只能用于用户能输入的内容(即可交互性元素的文本内容)
event对象
event : 事件对象 , 当一个事件发生的时候,和当前这个对象发生的这个事件有关的一些详细的信息都会被临时保存到一个指定地方---event对象,供我们在需要的调用。
Event 对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。
事件对象必须在一个事件调用的函数里面使用才有内容
事件函数:由事件调用的函数
兼容性
ie/chrome : event是一个内置全局对象
标准下 : 事件对象是通过事件函数的第一个参数传入
兼容性解决
document.onclick = function fn1(ev) {
var ev = ev || event;
}
如果一个函数是被事件调用的那么,这个函数定义的第一个参数就是事件对象
跟随鼠标移动小应用
var oDiv = document.getElementById('div1');
document.onmousemove = function(ev) {
var ev = ev || event; //解决兼容性
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
//clientX是获取到可视区顶部到鼠标的距离,当由滑动条时就不准确了,所以要加上 可视区顶部到页面顶部的距离scrollTop
oDiv.style.left = ev.clientX + 'px';
oDiv.style.top = ev.clientY + scrollTop + 'px';
}
事件流
事件传播
默认情况下,事件使用冒泡事件流,不使用捕获事件流。然而,在Firefox和Safari里,你可以显式的指定使用捕获事件流,方法是在注册事件时传入useCapture参数,将这个参数设为true。
事件冒泡
事件冒泡 : 当一个元素接收到事件(onclick onmouseover等)的时候,会把他接收到的事件传播给他的父级,在冒泡过程中的任何时候都可以终止事件的冒泡,如果不停止事件的传播,事件将一直通过DOM冒泡直至到达顶层window. 这种机制叫事件冒泡机制。
机理
function fn1() {
alert( this.id );
}
oDiv1.onclick = fn1; 给某某加事件,准确叫法给元素加事件处理函数
//加的不是事件,而是当有这个事件是需要执行的函数
//这称为事件函数绑定
oDiv1.onclick = fn1; //告诉div1,如果他接收到了一个点击事件,那么他就去执行fn1
//oDiv2.onclick = fn1; //虽然div2和div3注释了,但onclick还是有接受到的,只是发生了点击事件时不知道要执行什么而已
//oDiv3.onclick = fn1; //当点击div3时,会把点击事件onlick传给div2,div2再传给div1,div1有函数,则执行函数
应用:批量添加事件
如果想给几个/一堆元素添加相同的事件,只需要给这些元素的父级添加该事件即可
阻止冒泡 : 当前要阻止冒泡的事件函数中调用
非标准: event.cancelBubble = true;
标准:stopPropagation();
ex.
obj.onclick = function(ev) {
var ev = ev || event;
ev.cancelBubble = true; //阻止当前对象的当前事件的冒泡
ev.stopPropagation();
}
事件绑定的第二种方法 attachEvent、addEventListener
给一个对象绑定一个事件处理函数的第一种形式: obj.onclick = fn;
类似于赋值,绑定一个对象的同一个事件时,后面绑定的会覆盖前面的
给一个元素绑定事件函数的第二种形式
这种方法可以给一个对象的同一个事件绑定多个不同的函数
- ie:obj.attachEvent(事件名称,事件函数);
1.没有捕获
2.事件名称有on
3.事件函数执行的顺序:标准ie-》正序 非标准ie-》倒序
4.this指向window - 标准:obj.addEventListener(事件名称,事件函数,是否捕获);
1.有捕获
2.事件名称没有on
3.事件执行的顺序是正序
4.this指向触发该事件的对象
是否捕获 : 默认是false false:冒泡 true:捕获
兼容性解决:解决ie下this不是指向触发该事件的对象的问题
用call 函数下的一个方法
call方法第一个参数可以改变函数执行过程中的内部this的指向
call方法第二个参数开始就是原来函数的参数列表
function bind(obj, evname, fn) {
if (obj.addEventListener) {
obj.addEventListener(evname, fn, false);
} else {
obj.attachEvent('on' + evname, function() {
fn.call(obj); //使this指向触发该事件的对象
});
}
}
事件捕获
事件的处理将从DOM层次的根(顶部)开始,而不是从触发事件的目标元素开始,事件被从目标元素的所有祖先元素依次往下传递。在这个过程中,事件会被从文档根到事件目标元素之间各个继承派生的元素所捕获,如果事件监听器在被注册时设置了useCapture属性为true,那么它们可以被分派给这期间的任何元素以对事件做出处理;
否则,事件会被接着传递给派生元素路径上的下一元素,直至目标元素。事件到达目标元素后,它会接着通过DOM节点再进行冒泡。
默认情况下,事件使用冒泡事件流,不使用捕获事件流。
取消事件绑定的两种方法
- 直接赋null值
obj.onclick = null; //取消
- ie : obj.detachEvent(事件名称,事件函数);
- 标准 : obj.removeEventListener(事件名称,事件函数,是否捕获);
需要解决兼容性
键盘事件 onkeydown、onkeyup
onkeydown : 当键盘按键按下的时候触发
如果按下不抬起,那么会连续触发
onkeyup : 当键盘按键抬起的时候触发
不是所有元素都能够接收键盘事件,能够响应用户输入的元素(能够接收焦点的元素)才能够接收键盘事件
判断按下的是什么值
通过调用event对象下的keyCode属性
event.keyCode : 数字类型 键盘按键的值 键值
ctrlKey,shiftKey,altKey 布尔值 用来判断是否有按下
当一个事件发生的时候,如果ctrl || shift || alt 是按下的状态,返回true,否则 返回false
if (ev.keyCode == 13 && ev.ctrlKey) //同时按下两个键
事件默认行为
事件默认行为:当一个事件发生的时候浏览器自己会默认做的事情
怎么阻止?
当前这个行为是什么事件触发的,然后在这个事件的处理函数中使用return false;
ex.
obj.onkeydown = function() {
return false;
其他代码照写;
...
}
oncontextmenu : 右键菜单事件,当右键菜单(环境菜单)显示出来的时候触发
应用:自定义右键菜单
document.oncontextmenu = function(ev) {
var ev = ev || event;
oDiv.style.display = 'block';
oDiv.style.left = ev.clientX + 'px';
oDiv.style.top = ev.clientY + 'px';
return false; //阻止默认的右键菜单出现
}
document.onclick = function() {
oDiv.style.display = 'none'; //点击其他地方时菜单消失
}
事件深入应用
拖拽的原理及问题解决方法
由三个事件组成
- onmousedown : 选择元素
- onmousemove : 移动元素
- onmouseup : 释放元素
onmousemove、onmouseup被包在onmousedown里面;
另外可以封装成一个函数使用;
存在的问题
- 问题1:
拖拽的时候,如果有文字被选中,会产生问题
原因:当鼠标按下的时候,如果页面中有文字被选中,那么会触发浏览器默认拖拽文字的效果
解决方法:
标准:阻止默认行为(26行)
非标准ie:全局捕获(关于全局捕获解析看下文)(6,7,19,20行)
- 问题2:
用oDiv会导致拖动太快时,鼠标移出了oDiv就没有了onmousemove事件了
原因:onmousemove是每间隔一段时间检测有没有鼠标移动的,太快时,鼠标移出了oDiv
解决:看注释
拖拽图片会有问题,原因,解决的办法同上
oDiv.onmousedown = function(ev) {
var ev = ev || event;
var disX = ev.clientX - this.offsetLeft;
var disY = ev.clientY - this.offsetTop;
if ( oDiv.setCapture ) {
oDiv.setCapture();
}
document.onmousemove = function(ev) {
//oDiv.onmousemove = function(ev) { 用oDiv会导致拖动太快时,鼠标移出了oDiv就没有了onmousemove事件了,因为onmousemove是每间隔一段时间检测有没有鼠标移动的
var ev = ev || event;
oDiv.style.left = ev.clientX - disX + 'px';
oDiv.style.top = ev.clientY - disY + 'px';
}
document.onmouseup = function() {
document.onmousemove = document.onmouseup = null; //松开鼠标后不拖拽
if ( oDiv.releaseCapture ) { //释放全局捕获 releaseCapture();
oDiv.releaseCapture();
}
}
// oDiv.onmouseup = function() {
// document.onmousemove = oDiv.onmouseup = null;
// }用oDiv会导致:当有更高层级的元素挡住了被拖拽的元素时,onmouseup会失效
return false; //阻止默认行为
}
obj.setCapture();
设置全局捕获(和事件流的捕获不一样),当我们给一个元素设置全局捕获以后,那么这个元素就会监听后续发生的所有事件,当有事件发生的时候,就会被当前设置了全局捕获的元素所触发,且不像事件流捕获那样事件是共有的,而是只有该元素有事件,完全抢过去了
obj.releaseCapture(); 释放全局捕获
全局捕获兼容性:
ie : 有,并且有效果
ff : 有,但是没效果(不会报错)
chrome : 没有
拖拽应用之限制范围的拖拽
只需要在拖拽函数的基础上,赋值obj.style.left和obj.style.top前先限制一下left和top值(11-26行)
function drag(obj) {
obj.onmousedown = function(ev) {
var ev = ev || event;
var disX = ev.clientX - this.offsetLeft;
var disY = ev.clientY - this.offsetTop;
if ( obj.setCapture ) {
obj.setCapture();
}
document.onmousemove = function(ev) {
var ev = ev || event;
var L = ev.clientX - disX;
var T = ev.clientY - disY;
//限制左右
if ( L < 0 ) {
L = 0;
} else if ( L > document.documentElement.clientWidth - obj.offsetWidth ) {
L = document.documentElement.clientWidth - obj.offsetWidth;
}
//限制上下
if ( T < 0 ) {
T = 0;
} else if ( T > document.documentElement.clientHeight - obj.offsetHeight ) {
T = document.documentElement.clientHeight - obj.offsetHeight;
}
obj.style.left = L + 'px';
obj.style.top = T + 'px';
}
document.onmouseup = function() {
document.onmousemove = document.onmouseup = null;
if ( obj.releaseCapture ) {
obj.releaseCapture();
}
}
return false;
}
}
拖拽应用之磁性吸附(即靠近另外一个对象时会自动吸附过去)
只需要在拖拽限制范围函数的基础上,改一下判断条件即可(13行)
function drag(obj) {
obj.onmousedown = function(ev) {
var ev = ev || event;
var disX = ev.clientX - this.offsetLeft;
var disY = ev.clientY - this.offsetTop;
if ( obj.setCapture ) {
obj.setCapture();
}
document.onmousemove = function(ev) {
var ev = ev || event;
var L = ev.clientX - disX;
var T = ev.clientY - disY;
if ( L < 100 ) {
L = 0;
} else if ( L > document.documentElement.clientWidth - obj.offsetWidth ) {
L = document.documentElement.clientWidth - obj.offsetWidth;
}
if ( T < 0 ) {
T = 0;
} else if ( T > document.documentElement.clientHeight - obj.offsetHeight ) {
T = document.documentElement.clientHeight - obj.offsetHeight;
}
obj.style.left = L + 'px';
obj.style.top = T + 'px';
}
document.onmouseup = function() {
document.onmousemove = document.onmouseup = null;
if ( obj.releaseCapture ) {
obj.releaseCapture();
}
}
return false;
}
}
拖拽应用之磁性吸附碰撞检测
只需要在拖拽限制范围函数的基础上,改一下判断条件即可(11-31行);
function drag(obj) {
obj.onmousedown = function(ev) {
var ev = ev || event;
var disX = ev.clientX - this.offsetLeft;
var disY = ev.clientY - this.offsetTop;
if ( obj.setCapture ) {
obj.setCapture();
}
document.onmousemove = function(ev) {
var ev = ev || event;
var L = ev.clientX - disX;
var T = ev.clientY - disY;
var L1 = L;
var R1 = L + obj.offsetWidth;
var T1 = T;
var B1 = T + obj.offsetHeight;
var L2 = oImg.offsetLeft;
var R2 = L2 + oImg.offsetWidth;
var T2 = oImg.offsetTop;
var B2 = T2 + oImg.offsetHeight;
if ( R1 < L2 || L1 > R2 || B1 < T2 || T1 > B2 ) {
oImg.src = '1.jpg';
} else {
oImg.src = '2.jpg';
}
obj.style.left = L + 'px';
obj.style.top = T + 'px';
}
document.onmouseup = function() {
document.onmousemove = document.onmouseup = null;
if ( obj.releaseCapture ) {
obj.releaseCapture();
}
}
return false;
}
}
拖拽应用之拖拽改变层大小
只需要在拖拽限制范围函数的基础上,改一下即可(6-14行,20-27行);
这里只有改变左右的大小,上下一样道理;
function drag(obj) {
obj.onmousedown = function(ev) {
var ev = ev || event;
var disX = ev.clientX - this.offsetLeft;
var disY = ev.clientY - this.offsetTop;
var disW = this.offsetWidth;
var disL = this.offsetLeft;
var b = '';
if ( disX > disL + disW - 10 ) {
b = 'right';
}
if ( disX < disL + 10 ) {
b = 'left';
}
if ( obj.setCapture ) {
obj.setCapture();
}
document.onmousemove = function(ev) {
var ev = ev || event;
switch( b ) {
case 'left':
oDiv.style.width = disW - ( ev.clientX - disX ) + 'px';
oDiv.style.left = disL + ( ev.clientX - disX ) + 'px';
break;
case 'right':
oDiv.style.width = disW + ( ev.clientX - disX ) + 'px';
break;
}
}
document.onmouseup = function() {
document.onmousemove = document.onmouseup = null;
if ( obj.releaseCapture ) {
obj.releaseCapture();
}
}
return false;
}
}
拖拽应用之模拟滚动条控制内容滚动
等于拖拽加限制上下的范围;
var iMaxTop = oDiv1.offsetHeight - oDiv2.offsetHeight;
document.onmousemove = function(ev) {
var ev = ev || event;
var T = ev.clientY - disY;
if ( T < 0 ) {
T = 0;
} else if ( T > iMaxTop ) {
T = iMaxTop;
}
oDiv2.style.top = T + 'px';
var iScale = T / iMaxTop; //滚动条目前位置占滚动条总长度的比例
内容元素.style.top = (包着内容的元素.clientHeight - 内容元素.offsetHeight) * iScale + 'px';
}
鼠标滚轮和cookie
鼠标滚轮
ie/chrome : onmousewheel
其他浏览器不支持但也不报错,相当于添加了一个自定义属性onmousewheel
判断滚上滚下event.wheelDelta
上:120
下:-120
firefox : DOMMouseScroll
必须用addEventListener绑定(非标准下会报错,因为没有addEventListener)
判断滚上滚下event.detail
上:-3
下:3
兼容性解决
通过布尔值判断上下
function fn(ev) {
var ev = ev || event;
var b = true;
if (ev.wheelDelta) {
b = ev.wheelDelta > 0 ? true : false;
} else {
b = ev.detail < 0 ? true : false;
}
当页面有滑动条时,滚轮默认是滑动 滑动条的,要阻止这个默认行为
if (ev.preventDefault) {
ev.preventDefault();
}
return false;
return false阻止的是 obj.on事件名称=fn 所触发的默认行为
addEventListener绑定的事件需要通过event下面的preventDefault();
cookie
cookie : 存储数据,当用户访问了某个网站(网页)的时候,我们就可以通过cookie来向访问者电脑上存储数据
- 不同的浏览器存放的cookie位置不一样,也是不能通用的
- cookie的存储是以域名形式进行区分的
- cookie的数据可以设置名字的
- 一个域名下存放的cookie的个数是有限制的,不同的浏览器存放的个数不一样
- 每个cookie存放的内容大小也是有限制的,不同的浏览器存放大小不一样
我们通过document.cookie来获取当前网站下的cookie的时候,得到的字符串形式的值,他包含了当前网站下所有的cookie。他会把所有的cookie通过一个分号+空格的形式串联起来
cookie可读可写
document.cookie = '名字=值';
alert(document.cookie);
cookie默认是临时存储的,当浏览器关闭进程的时候自动销毁
如果我们想长时间存放一个cookie。需要在设置这个cookie的时候同时给他设置一个过期的时间
document.cookie = '名称=值;expires=' + 字符串格式的时间;
var oDate = new Date();
oDate.setDate( oDate.getDate() + 5 );//getDate获取当前时间,+5表示加上5天
上面的方法得到的是obj类型,要转换成字符串类型
oDate.toGMTString();
内容有特殊字符时,为了避免出现问题,内容最好编码encodeURI存放,读取时再解码decodeURI;
document.cookie = 'username='+ encodeURI('leo\n你好') +';expires=' + oDate.toGMTString();
alert(decodeURI(document.cookie));//username=leo;
封装成函数:
setCookie
function setCookie(key, value, t) {
var oDate = new Date();
oDate.setDate( oDate.getDate() + t );
document.cookie = key + '=' + value + ';expires=' + oDate.toGMTString();
}
getCookie
function getCookie(key) {
var arr1 = document.cookie.split('; ');//用分号+空格拆分成数组
for (var i=0; i<arr1.length; i++) {
var arr2 = arr1[i].split('=');//拆分后再把cookie的名称和值分开
if ( arr2[0] == key ) {
return decodeURI(arr2[1]);
}
}
}
removeCookie
function removeCookie(key) {
setCookie(key, '', -1);//只需要设置一个已过期的时间
}