js分三个部分:
ECMAScript标准:js的基本语法
DOM:Ducument Object Model--->文档对象模型--->操作页面的元素
BOM:Browser Object Model--->浏览器对象---->操作浏览器
1,什么是api-----可以理解为一套方法(或者工具)
2,什么是webapi-----那就是网络提供的方法(或者工具)
获取页面元素的几种方法
1,根据标签名获取元素
document.getElementsByTagName('div'); // 能够获取所有div标签
可以通过已找到的元素来调用
2,根据标签的class属性获取元素
document.getElementsByClassName('nav'); // 能够获取所有class="nav"的元素
可以通过已找到的元素来调用
在IE9以后的版本才支持!
3,根据标签的name属性获取元素
document.getElementsByName('mv'); // 能获取所有name="mv"的元素
在不同浏览器工作的方式不同,在IE和Opera浏览器下这个方法
将返回具有id属性和name属性是这个值的!
4,根据标签的id属性获取元素
document.getElementById('btn'); // 只能获取第一个id="btn"的元素
只能通过document来调用!
5,根据选择器来查找元素:
document.querySelector('ul li'); // 只能获取第一个元素
document.querySelectorAll('ul li'); // 可以获取ul下的所有li元素
有浏览器兼容性问题,在IE8以后的版本才会执行。移动端开发可以直接使用,不用担心兼容性问题
事件1
事件:就是当什么时候做什么事情
触发~响应
1,先获取元素
2,给元素注册事件
事件名称
事件源
事件处理函数
实例:点击按钮后弹出窗口
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试</title>
</head>
<body> <input type="button" value="点我" id="btn">
<script>
// 先获取元素
var btn = document.getElementById('btn');
// 注册事件
btn.onclick = function () {
alert('点到我了');
} </script> </body>
</html>
例子1:点击按钮切换图片
<!DOCTYPE>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试</title>
</head>
<input type="button" value="点我" id="btn">
<br />
<img src="data:images/a.jpg" id="mv" /> <script>
// 获取元素
var btn = document.getElementById('btn');
var mv = document.getElementById('mv');
// 标志位,保证两种照片可以来回切换
var flag = true;
// 注册事件
btn.onclick = function () {
if (flag) {
mv.src = 'images/b.jpg';
flag = false;
} else {
mv.src = 'images/a.jpg';
flag = true;
}
}
</script>
</html>
属性操作
非表单的属性 : 只展示出来给用户看
表单元素:可以和用户进行交互 如 input button
非表单的属性: href, title, alt, id, src, className
而这些属性都是可以修改的
实例:
<!DOCTYPE>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试</title>
</head>
<a href="http://www.baidu.com" id="link">百度</a>
<script> var link = document.getElementById('link');
// 修改链接
link.href = 'http://www.jd.com'; </script>
</html>
例子:点击按钮div显示或隐藏
<!DOCTYPE>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试</title>
<style>
* {
margin: ;
padding: ;
}
#box {
width: 200px;
height: 200px;
background-color: pink;
}
.show {
display: block;
}
.hidden {
display :none;
} </style>
</head>
<input type="button" value="隐藏" id="btn">
<br />
<div class="show" id="box"></div> <script> // 获取元素
var btn = document.getElementById('btn');
// 标志位,控制来回切换
var isShow = true;
// 注册事件
btn.onclick = function () {
// 获取元素
var box = document.getElementById('box'); // div是否显示
if (isShow) {
// 修改元素的类名
// className为什么DOM对象的对应标签的class属性的名字叫做className,
// 因为class在javascript中是关键字,关键字不可以作为变量或者属性的名字。
box.className = 'hidden';
// 修改按键的属性。
// this的几种情况:
// 1,在函数内----指向window
// 2,在构造函数中----指向的是构造函数创建的对象
// 3,在方法中----指向的是这个方法所属的对象
// 4,在事件处理函数中----谁调用该事件,this就指向谁
this.value = '显示';
isShow = false;
} else {
box.className = 'show';
this.value = '隐藏';
isShow = true;
}
} </script>
</html>
取消a标签的默认行为:不会跳转到href指定的页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<a href="http://www.baidu.com" id="link">百度</a> <script>
// 获取元素
var link = document.getElementById('link'); // 注册事件
link.onclick = function () {
alert('hello world');
// 重要的一步:取消a标签的默认行为
return false;
} </script>
</body>
</html>
test
job:相册(来回切换照片)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
/** {
padding: 0;
margin: 0;
}*/
/* 清除浮动*/
.clearfix:after {
content: ;
display: block;
height: ;
visibility: hidden;
clear: both;
}
.clearfix {
*zoom: ;
} /*a标签*/
#imagegallery a {
display: inline-block;
margin: 20px 20px ;
padding: ;
text-decoration: none;
}
#imagegallery a img {
border: ;
} </style>
</head>
<body>
<h2>
美女画廊
</h2>
<div id="imagegallery" class="clearfix">
<a href="images/1.jpg" title="美女A">
<img src="data:images/1-small.jpg" width="100px" alt="美女1">
</a>
<a href="images/2.jpg" title="美女B">
<img src="data:images/2-small.jpg" width="100px" alt="美女2">
</a>
<a href="images/3.jpg" title="美女C">
<img src="data:images/3-small.jpg" width="100px" alt="美女3">
</a>
<a href="images/4.jpg" title="美女D">
<img src="data:images/4-small.jpg" width="100px" alt="美女4">
</a>
</div> <img id="image" src="data:images/placeholder.png" width="450px" />
<p id="des">请选择一张照片</p> <script>
// 获取所有的a元素
var imagegallery = document.getElementById('imagegallery');
var links = imagegallery.getElementsByTagName('a'); // 给所有的a元素添加事件
for (var i = ; i < links.length; i++) {
// 所有的a标签对应的元素
var link = links[i];
link.onclick = function () {
// 获取占位图
var image = document.getElementById('image');
// 切换图片
image.src = this.href; // 获取p元素
var des = document.getElementById('des'); // 设置p标签的内容
des.innerText = this.title; //取消a标签的默认行为
return false;
}
}
</script>
</body>
</html>
job
打印对象:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="box">
hello world
<span>Hi</span>
</div> <script>
// 获取元素
var box = document.getElementById('box');
// 打印这个对象
console.dir(box); // div#box
// 获取内部文本
console.log(box.innerText); // hello world Hi
// 获取内部文本和标签(有标签时)
console.log(box.innerHTML); // </script>
</body>
</html>
test
innerHTML:获取内部文本和标签(如果有标签)
innerText / textContent:获取内部文本(不包含标签),有浏览器兼容问题
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="box">hello</div>
<script>
// innerText的浏览器兼容处理
function getInnerText(element) {
// 判断是否有innerText属性
if (typeof element.innerText === 'string') {
// 浏览器支持innerText则使用
return element.innerText;
} else {
// 浏览器不支持innerText,则使用textContent
return element.textContent;
}
}
// 获取元素
var box = document.getElementById('box');
// 传入函数
alert(getInnerText(box)) </script>
</body>
</html>
innerText的浏览器兼容处理
设置内容时该什么方法:
innerText / textContent // 内容不带标签
innerHTML // 内容带标签
当设置不含标签的内容时候,应该使用innerText,它的效率高!
表单元素属性:
value // 用于大部分表单元素的内容获取(option 除外)
type // 可以获取input标签的类型(输入框或复选框等)
checkeed // 复选框选中属性。(返回的值是布尔类型)
selected // 下拉菜单选中属性。(返回的值是布尔类型)
文本域的相关属性设置:
disabled // 禁用属性。让用户无法输入内容。(返回的值是布尔类型)
readOnly // 只读不能修改
.value // 可以修改文本域里面的内容---建议使用这种
.innerText // 可以修改文本域里面的内容
job:点击按钮禁用文本框
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<input type="button" value="点我" id="btn">
<input type="button" value="写入内容" id="btn1">
<br />
<input type="text" id="text" value="">
<script> // 获取元素
var btn = document.getElementById('btn'); // 注册事件
btn.onclick = function () {
var text = document.getElementById('text');
// 禁止属性。只是让用户无法输入。但还是可以通过代码写入内容
text.disabled = true;
} // 获取元素
var btn1 = document.getElementById('btn1'); // 注册事件
btn1.onclick = function () {
// 获取元素
var text = document.getElementById('text');
// 写入内容。
text.value = 'hello world';
} </script>
</body>
</html>
job
job:给文本框赋值,获取文本框的值---两种实现方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
input {
display: block;
margin: 10px 10px;
} </style>
</head>
<body>
<input type="text" name="" id="">
<input type="text" name="" id="">
<input type="text" name="" id="">
<input type="text" name="" id="">
<input type="text" name="" id="">
<input type="text" name="" id="">
<input type="text" name="" id="">
<input type="text" name="" id="">
<input type="text" name="" id="">
<input type="text" name="" id="">
<input type="button" value="获取文本框的值" id="btn"> <script>
// 给文本框赋值,获取文本框的值 // 1,先给文本框赋值
//
// 获取所有input元素
var inputs = document.getElementsByTagName('input'); // 拿到每一个input元素
for (var i = ; i < inputs.length; i++) {
var input = inputs[i];
// 判断是不是文本框
if (input.type === 'text') {
input.value = i;
}
} // 2,获取文本框的值
//
// 获取btn元素
var btn = document.getElementById('btn'); // 注册事件
btn.onclick = function () { // 存储全部文本框的值
var array = []; // 获取所有文本框的值
for (var i = ; i < inputs.length; i++) {
// 判断是不是文本框
var input = inputs[i];
if (input.type === 'text') {
array.push(input.value);
}
} // 拼接成0|1|2|3|4|5|6|7|8|9
var s = array.join('|');
console.log(s); }
</script>
</body>
</html>
实现方法1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
input {
display: block;
margin: 10px ;
} </style>
</head>
<body>
<input type="text" name="" id="">
<input type="text" name="" id="">
<input type="text" name="" id="">
<input type="text" name="" id="">
<input type="text" name="" id="">
<input type="text" name="" id="">
<input type="text" name="" id="">
<input type="text" name="" id="">
<input type="text" name="" id="">
<input type="text" name="" id="">
<input type="button" value="获取所有属性的值" id="btn"> <script>
// 1,给所有文本框赋值
//
// 获取所有input元素
var inputs = document.getElementsByTagName('input'); // 遍历所有input元素
for (var i = ; i < inputs.length; i++) {
var input = inputs[i];
// 判断是不是文本框
if (input.type === 'text') {
// 给文本框赋值
input.value = i;
}
} // 2,获取所有文本框中的值,并拼接 // 获取按钮元素
var btn = document.getElementById('btn'); // 注册事件
btn.onclick = function () { // 存储所有文本框的值
var str = '';
// 遍历所有input元素
for (var i = ; i < inputs.length; i++) {
var input = inputs[i];
// 判断是不是文本框
if (input.type === 'text') {
// 拼接字符串
str += input.value + '|';
}
}
var s = str.substr(, str.length - );
console.log(s);
} </script>
</body>
</html>
实现方法2
自定义属性 :
setAttribute('属性名', '值') // 设置自定义属性
getAttribute('属性名') // 获取自定义属性的值
removeAttribute('属性名') // 移除自定义属性或者自带属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div> <input type="button" value="移除自定义属性" id="btn"/> <script>
var Objs = document.getElementsByTagName('div');
// 遍历
for (var i = ; i < Objs.length; i++) {
// 设置自定义属性和值
Objs[i].setAttribute('num', (i + ));
// 根据标签名获取元素,为元素注册点击事件,添加事件处理函数
Objs[i].onclick = function () {
// 获取自定义属性的值
alert(this.getAttribute('num'));
};
} // 根据id获取元素,注册点击事件,添加事件处理函数
document.getElementById('btn').onclick = function () {
// 遍历
for (var i = ; i < Objs.length; i++) {
// 移除自定义属性
Objs[i].removeAttribute('num');
}
};
</script>
</body>
</html>
test
节点:node
介绍:
1,页面上的所有内容都是节点:标签是节点,属性是节点,文本也是节点(文本有文字空格换行)
2,获取标签元素非常方便
节点的属性:
节点的属性:(可以使用标签(元素).出来,可以使用属性节点.出来,文本节点.点出来)
节点的类型 nodeType // 1 标签节点,2 属性节点,3 文本节点
节点的名字 nodeName // 大写标签名 标签节点,小写属性名 属性节点,#text 文本节点
节点的值 nodeValue // Null 标签节点,属性名 属性节点,文本的内容
获取节点:
1,只有标签才能作为父节点
2, .parentNode,.parentElement支持所有浏览器(谷歌,火狐,IE8)
3,.childNodes,children也支持所有浏览器(谷歌,火狐,IE8)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>kay</title>
</head>
<body>
<input type="button" value="获取" id="btn"/>
<ul id="uls">
<li>kay1</li>
<li>kay2</li>
<li>kay3</li>
<li id="middle">kay4</li>
<li>kay5</li>
<li>kay6</li>
<li>kay7</li>
</ul>
<script>
// 根据id获取按钮,注册点击时间,添加事件处理函数
document.getElementById('btn').onclick = function () {
// 根据id获取元素li
var middle = document.getElementById('middle');
// 获取父节点
console.log(middle.parentNode); // 获取到整个ul
// 获取父元素
console.log(middle.parentElement); // 获取到也是整个ul
// 获取前一个兄弟元素
console.log(middle.previousElementSibling); // 获取到kay3
// 获取前一个兄弟节点
console.log(middle.previousSibling); // 返回#text(就是距离前一个元素中间的那段换行)
}
</script>
</body>
</html>
test
//获取父节点
parentNode
//获取父元素
parentElement
// 获取子节点
childNodes
//获取子元素
children
//获取第一个子节点
firstChild
// 获取第一个子元素
firstElementChild
//获取最后一个子节点
lastChild
//获取最后一个子元素
lastElementChild
//获取前一个节点
previousSibling
//获取前一个元素
previousElementSibling
//获取后一个节点
nextSibling
//获取后一个元素
nextElementSibling
获取节点的方法
浏览器兼容问题:
1,在IE8获取子节点和兄弟节点被变成获取子元素和兄弟元素
2,在IE8获取父节点和父元素可以正常获取
//总结:凡是获取节点的代码在谷歌和火狐得到的都是 相关的节点
//凡是获取元素的代码在谷歌和火狐得到的都是 相关的元素
//从子节点和兄弟节点开始,凡是获取节点的代码在IE8中得到的是元素,获取元素的相关代码,在IE8中得到的是undefined----元素的代码,iE中不支持
// 获取任意一个父级元素的第一个子元素
function getFirstElementChild(element) {
// 判断浏览器是否支持
if (typeof element.firstElementChild !== 'undefined') {
// 返回第一个子元素
return element.firstElementChild;
} else {
// node=第一个字节点
var node = element.firstChild;
// node.nodeType !== 1(不是标签)
while (node && node.nodeType !== ) {
// // node = 后一个字节点
node = node.nextSibling;
}
return node;
}
} // 获取任意一个父级元素的最后一个子元素
function getLastElementChild(element) {
//
if (typeof element.lastElementChild !== 'undefined') {
return element.lastElementChild;
} else {
// node=最后一个子节点
var node = element.lastChild;
// node.nodeType !== 1(不是标签)
while (node && node.nodeType !== ) {
// node = 前一个字节点
node = node.previousSibling;
}
// 返回节点
return node;
} }
解决IE8兼容问题
创建元素:元素创建的三种方式:
1,document.write('标签的代码及内容')
// 缺陷:如果在页面加载完毕后,通过这种方式创建元素,会把页面的所有内容都清除(只剩下这个创建的元素)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>kay</title>
</head>
<body>
<input type="button" value="获取" id="btn"/>
<ul id="uls">
<li>kay1</li>
<li>kay2</li>
<li>kay3</li>
<li id="middle">kay4</li>
<li>kay5</li>
<li>kay6</li>
<li>kay7</li>
</ul>
<script>
// 根据id获取按钮,注册点击时间,添加事件处理函数
document.getElementById('btn').onclick = function () {
document.write('<p>哈哈页面消失了吧</p>');
}
</script>
</body>
</html>
test
2,对象.innerHTML='标签及代码'
// 在谁里面创建就应该是(谁.innerHTML)
document.getElementById('btn').onclick = function () {
var middle = document.getElementById('middle');
middle.innerHTML = '<p>见证奇迹的时刻</p>';
}
test
3,document.createElement('标签的名字')
// 根据id获取按钮,注册点击时间,添加事件处理函数
document.getElementById('btn').onclick = function () {
// 创建p元素
var p = document.createElement('p');
// 设置p元素中间内容
p.innerText = '见证奇迹';
// 把创建的子元素,追加到父元素里面
document.getElementById('middle').appendChild(p);
}
test
元素相关操作:
.appendChile(newChild) // 追加子元素
.insertBefore (newChild,refChild) // 在某元素之前插入新元素。.insertAfter在某元素之后插入新元素
.replaceChild (newChild,refChild) // 替换子元素
.removeChild(oldChild) // 移除子元素
job:
// 第一种实现方式
my$('btn').onclick = function () {
// 如果这个按钮存在
if (my$('btn1')) {
// 移除这个按钮
my$('dv').removeChild(my$('btn1'));
}
// 创建按钮
var input = document.createElement('input')
input.type = 'button';
input.value = '按钮';
input.id = 'btn1';
// 追加
my$('dv').appendChild(input);
};
//---------------------
// 第二种实现方式
my$('btn').onclick = function () {
// 判断这个按钮是否存在
if (!my$('btn1')) { // 按钮不存在
var obj = document.createElement('input');
obj.type = 'button';
obj.value = '按钮';
obj.id = 'btn1';
my$('dv').appendChild(obj);
}
}
只创建一个按钮
事件2
绑定事件的三种方式:
addEventListener和attachEvent可以绑定多个相同事件!
a,.on事件名=事件处理函数 // 谷歌,火狐,IE8都支持
缺点:不能绑定多个相同事件,假如绑定多个的话最终只有一个。
b,.addEventListener(type,listener,useCapture) //只有谷歌和火狐支持
//参数1:事件的类型---事件的名字,没有on
//参数2:事件处理函数---函数(命名函数,匿名函数)
//参数3:布尔类型,目前就写false
// 不支持IE8
document.getElementById('btn').addEventListener('click', function () {
console.log('hello');
}, false);
test
c,.attachEvent(type,listener) //只有IE8支持
//参数1:事件类型---事件名字,有on
//参数2:事件处理函数---函数(命名函数,匿名函数)
// 只支持IE8
document.getElementById('btn').attachEvent('onclick', function () {
console.log('hello');
});
test
解绑事件:对应以上的三种解绑方法
注意:用什么方式绑定事件,就应该用对应的方式解绑事件
a,对象.on事件名=null
// 绑定
document.getElementById('btn1').onclick = function () {
console.log('kay');
} document.getElementById('btn2').onclick = function () {
// 解绑
document.getElementById('btn1').onclick = null;
}
on
b,对象.removeEventListener('不带on的事件名', 函数名, false)
// 命名函数
function f1() {
console.log('hello')
}
// 绑定 document.getElementById('btn1').addEventListener('click', f1, false) document.getElementById('btn2').onclick = function () {
// 解绑 document.getElementById('btn1').removeEventListener('click', f1, false);
};
addEventListener
c,对象.detachEvent(带on的事件名, 函数名)
// 命名函数
function f2() {
console.log('kay');
}
// 绑定
document.getElementById('btn1').attachEvent('onclick', f2);
//
document.getElementById('btn2').onclick = function () {
// 解绑
document.getElementById('btn1').detachEvent('onclick', f2);
};
detachEvent
解决浏览器兼容问题:
// 为任意元素绑定任意事件
function addEventListener(element, type, fn) {
// 如果浏览器有这个方法,谷歌,火狐
if (element.addEventListener) {
element.addEventListener('click', fn, false);
// IE8的
} else if (element.attachEvent) {
element.attachEvent('on' + type, fn);
} else {
element['on' + type] = null;
}
} // 两个命名函数
function f1() {
console.log('kay1');
}
function f2() {
console.log('kay2');
}
var btn1 = document.getElementById('btn1');
// 绑定两个点击事件
addEventListener(btn1, 'click', f1);
addEventListener(btn1, 'click', f2);
绑定多个相同事件
// 为任意元素解绑事件
function removeEventListener(element, type, fnName) {
// 如果浏览器有这个方法
if (element.removeEventListener) {
element.removeEventListener(type, fnName, false);
} else if (element.detachEvent) {
element.detachEvent('on' + type, fnName);
} else {
element['on' + type] = null;
}
} // 解绑事件
removeEventListener(btn1, 'click', f2);
解绑事件
事件冒泡:
事件冒泡解释:
多个元素嵌套,有层次关系,这些元素都注册了相同的事件,
如果里面的元素的事件触发了,
外面的元素的该事件自动的触发了.
<div id="dv1">
<div id="dv2">
<div id="dv3"></div>
</div>
</div>
<script>
// 最外层
document.getElementById('dv1').onclick = function () {
console.log('外层===' + this.id);
};
// 第二层
document.getElementById('dv2').onclick = function () {
console.log('第二层===' + this.id);
};
// 最里层
document.getElementById('dv3').onclick = function () {
console.log('最里层===' + this.id);
};
</script>
事件冒泡
阻止事件冒泡:
1,window.event.cancelBubble = true; // 谷歌和IE8支持,火狐不支持
2,e.stopPropagation(); // 谷歌和火狐支持,IE8不支持
这种使用的是事件处理函数的参数对象.方法()
document.getElementById('dv1').onclick = function () {
console.log('外层===' + this.id);
};
document.getElementById('dv2').onclick = function () {
console.log('第二层===' + this.id);
// 阻止事件冒泡第一种
// window.event.cancelBubble = true;
};
// function (参数对象)
document.getElementById('dv3').onclick = function (e) {
console.log('最里层===' + this.id);
// 阻止事件冒泡第二种,
e.stopPropagation();
};
阻止事件冒泡
事件分三个阶段:
1捕获阶段 --- 从外到里
2目标阶段
3冒泡阶段 --- 从里到外
e.eventPhase // 调用事件处理程序的阶段
// 命名函数
function fn(e) {
var current = '';
// 判断事件处于哪个阶段
switch (e.eventPhase) {
case :
current = '捕获阶段';
break;
case :
current = '目标阶段';
break;
case :
current = '冒泡阶段';
break;
}
console.log(this.id + '===' + current);
}
查看当前事件处于哪阶段
//
var dv1 = document.getElementById('dv1');
var dv2 = document.getElementById('dv2');
var dv3 = document.getElementById('dv3');
var objs = [dv1, dv2, dv3];
// 为数组中每个元素注册点击事件
objs.forEach(function(item) {
// true捕获阶段,false冒泡阶段
item.addEventListener('click', fn, false)
});
控制捕获或者冒泡
被点击的div3就是:目标阶段
job:为同一元素绑定多个不同事件,并使用同一个事件处理函数
// 命名函数
function fn(e) {
switch(e.type) {
case 'click':
alert('kay,hellow');
break;
case 'mouseover':
this.style.backgroundColor = 'hotpink';
break;
case 'mouseout':
this.style.backgroundColor = 'green';
break;
}
}
var btn = document.getElementById('btn');
// 为按钮绑定:点击,鼠标进入,鼠标离开事件
btn.addEventListener('click', fn, false);
btn.addEventListener('mouseover', fn, false);
btn.addEventListener('mouseout', fn, false);
job