DOM特效封装
注意:为了达到各个浏览器之间的兼容问题,下面的Js文件是已经封装好了的方法,下面的某些案例为了避免重复代码,故有的文件则会引用如下几个JS文件.
L.js
(function(w){
var L = w.L ? w.L : {}; // 定义L框架的根。
// 我们占用了全局的L变量名。
L.Dialog = function(selector) {
// 先判断选择器对应之前已经创建过了吗?如果创建过了直接返回对象。
if(L.Dialog.cache[selector]) {
return L.Dialog.cache[selector];
}
// 接受用户传来的选择器
// 1、要有一个 show方法, 弹出对话框。
// 2、 关闭方法 close
// 3、动态解析用户的输入信息。
var dialogDiv = document.querySelector(selector);
if(!dialogDiv) {
return null;
}
// 拿到用户给的标题文本。
var title = dialogDiv.getAttribute('title');
// 初始化遮罩层。
var dialogCover = document.createElement('div');
dialogCover.className = "dialog-cover";
dialogCover.style.display = "none";
document.body.appendChild(dialogCover);
var strHTML = "";
strHTML += '<div class="dialog">';
strHTML +=' <div class="dialog-h">';
strHTML +=' <h3>' + title + '</h3>';
strHTML +=' <i class="btn-close" id="">X</i>'
strHTML +=' </div>'
strHTML +=' <div class="dialog-b">'
strHTML += dialogDiv.innerHTML;
strHTML +=' </div>'
strHTML +=' </div>'
dialogDiv.innerHTML = strHTML;
var dialog = {
dialogDiv: dialogDiv, // 用户的dialog的div
title: title, // 用户的标题
dialogCover: dialogCover, // 遮罩层属性。
show: function() {
// 弹出层
// 第一个显示 遮罩层, 第二个显示对话框 第三个,给关闭按钮绑定点击事件。
this.dialogCover.style.display = "block";
this.dialogDiv.style.display = "block";
var self = this;
var btnClose = dialogDiv.querySelector('.btn-close');
btnClose.onclick = function() {
self.close();
}
},
close: function() {
// 关闭层
// 第一个不显示 遮罩层, 第二个不显示对话框 第三个,给关闭按钮去掉绑定点击事件。
this.dialogCover.style.display = "none";
this.dialogDiv.style.display = "none";
var self = this;
var btnClose = dialogDiv.querySelector('.btn-close');
btnClose.onclick = null;
}
};
L.Dialog.cache[selector] = dialog;
return dialog;
}
// 在函数上创建一个缓存。 放 selector 对应的 dialog对象。
L.Dialog.cache = {};
w.L = L;
})(window || {});
/* 封装 动画的效果方法 */
(function(w){
var L = w.L ? w.L : {}; // 定义L框架的根。
// 我们占用了全局的L变量名。
/**
* @description 进行slideDown动画的方法
* @param {HTMLElemnet} element 要进行动画的元素
* @param {number} duration 持续的事件
* @return {undefined}
*/
L.slideDown = function(element, duration) {
var start = Date.now(); // 开始动画的时间。
element.style.display = "block";
var originH = element.clientHeight;
element.style.height = '0px';
var timer = setInterval(function(){
var now = Date.now();
element.style.height = (now-start)/duration * originH + 'px';
if(now-start >= duration) {
element.style.height = originH + 'px';
clearInterval(timer);
}
}, 1000/60);
};
w.L = L;
})(window || {});
案例:65-模态对话框-面向对象封装
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>65-模态对话框.html</title>
<style>
html,
body,
div,
h3 {
padding: 0;
margin: 0;
}
.dialog-wrap {
display: none;
}
.dialog {
position: absolute;
left: 50%;
top: 50%;
margin-top: -151px;
margin-left: -151px;
background-color: #eee;
border: 1px solid #ccc;
width: 300px;
/* display: none; */
z-index: 1000;
}
.dialog .dialog-h {
border-bottom: 1px solid #ccc;
height: 30px;
position: relative;
}
.dialog-b {
height: 269px;
}
.dialog-h .btn-close {
position: absolute;
right: 15px;
top: 5px;
cursor: pointer;
}
.dialog-cover {
/* 如果一个div的父容器为body,而且是绝对定位,那么left和top、bottom、right都为0
的时候就会铺满正个屏幕 */
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
z-index: 100;
/* 设置透明 */
filter: alpha(opacity=70);
opacity: 0.7;
}
</style>
<script src="../js/L.js"></script>
</head>
<body>
<input type="button" value="弹出对话框" id="btn">
<!-- 规定: 用户要使用dialog对话框,必须 -->
<!-- 1、div 的class = dialog-wrap -->
<!-- 2、需要给div增加 title属性,如果没有增加,那么标题就是空的 -->
<!-- 3、div的innerHTML就是显示在对话框上的信息 -->
<div id="mDialog" class="dialog-wrap" title="弹出来的对话框">
在对话框里面显示的内容
<p>好样的!!</p>
<input type="button" value="关闭">
</div>
<script>
window.onload = function () {
var btn = document.getElementById('btn');
btn.onclick = function () {
var dialog = new L.Dialog("#mDialog");// 如果用户没有用new,也不会报错。
// 在 #mDialog上进行创建一个模态对话框。
// var dialog = new Dialog("#mDialog");
// 可能框架有多个 组件。要兼容扩展其他的组件。 L框架
dialog.show(); // 弹出对话框了。
}
}
</script>
<h1>1</h1>
<h1>2</h1>
<h1>3</h1>
<h1>4</h1>
<h1>5</h1>
<h1>6</h1>
<h1>7</h1>
<h1>8</h1>
<h1>9</h1>
<h1>10</h1>
<h1>11</h1>
<h1>12</h1>
<h1>13</h1>
<h1>14</h1>
<h1>15</h1>
<h1>16</h1>
<h1>17</h1>
<h1>18</h1>
<h1>19</h1>
<h1>20</h1>
<h1>21</h1>
<h1>22</h1>
<h1>23</h1>
<h1>24</h1>
<h1>25</h1>
<h1>26</h1>
<h1>27</h1>
<h1>28</h1>
<h1>29</h1>
<h1>30</h1>
</body>
</html>
DOM特效封装
案例:66-slideDown
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>slideDown</title>
<style>
html, body, div {
padding: 0;margin: 0;
}
.box {
border: 1px solid #ccc;
width: 300px;
height: 300px;
background-color: #eee;
}
.wrap {
width: 960px;
margin: 0 auto;
}
</style>
</head>
<body>
<div class="wrap">
<input type="button" value="折叠" id="btnSlideUp">
<input type="button" value="展开" id="btnSlideDown">
<div class="box" id="box">
我是box
</div>
</div>
<script>
(function(){
window.onload = function(){
var btnSlideUp = document.getElementById('btnSlideUp'),
btnSlideDown = document.getElementById('btnSlideDown'),
box = document.getElementById('box');
btnSlideDown.onclick = function() {
slideDown(box, 100);
// var start = Date.now(); // 最开始的的事件。
// // 如果div的display为none那么 clientHeight 0
// box.style.display = "block";
// var originH = box.clientHeight;// 最开始的高度
// box.style.height = "0px";
// var timer = setInterval(function(){
// var now = Date.now();
// box.style.height = (now - start) / 500 * originH + 'px';
// if(now - start >= 500) {
// box.style.height = originH + 'px';
// clearInterval(timer);
// }
// }, 1000/60);
}
// 点击 折叠按钮后,让div一点一点进行向上折叠。
btnSlideUp.onclick = function(e) {
var start = Date.now(); // 返回当前时间的utc时间,1970 毫秒数
// 随着时间的推移,让div的高度一直减小。到最后为0. display:none
var originH = box.clientHeight;// 拿到显示的高度。div height
// 1秒钟后,div消失。1000ms
var timer = setInterval(function(){
// var now = Date.now();
// console.log(now - start);// 两个事件相差的毫秒数。16
// start = now;
// 思路一: 当前事件和上一次执行的相隔事件执行div的减少高度操作。
// 思路二: 当前事件跟最一开始的时间进行计算。把相差总时间换算成
// 应该减少的高度,然后设置div的高度。
var now = Date.now();
// 要减少的高度
var nowH = (now - start) * originH / 1000;
// 当前div的高度 = 原来的高度 - 要减少的高度
box.style.height = (originH - nowH) + 'px';
if(originH <= nowH) {
// 停止折叠,并且把当前div 隐藏起来。并且把时钟去掉。
box.style.height = originH + "px"; // 隐藏之后还要把它恢复到原来的状态。
box.style.display = "none";
clearInterval(timer);
}
},1000/60);
//问题1: 1000/60 ,setInterval执行 的不是严格按照时间间隔去执行。
};
};
})();
/**
* @description 进行向下展开的函数
* @param {HTMLElement} element - 要进行动画的标签
* @param {number} duration - 动画持续的事件
* @return {undefined}
**/
function slideDown(element, duration) {
var start = Date.now(); // 开始动画的时间。
element.style.display = "block";
var originH = element.clientHeight;
element.style.height = '0px';
var timer = setInterval(function(){
var now = Date.now();
element.style.height = (now-start)/duration * originH + 'px';
if(now-start >= duration) {
element.style.height = originH + 'px';
clearInterval(timer);
}
}, 1000/60);
}
</script>
</body>
</html>
DOM特效封装 - 68-轮播图效果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>轮播图</title>
<style>
html,
body,
div,
ul,
li {
padding: 0;
margin: 0;
}
ul,
ol {
list-style: none;
}
a {
text-decoration: none;
color: #000;
}
.slideshow {
width: 500px;
height: 300px;
border: 1px solid #ccc;
margin: 100px auto;
overflow: hidden;
position: relative;
}
.slideshow .slide-img-wrap {
width: 2000px;
position: absolute;
left: 0;
top: 0;
z-index: 1;
}
.slideshow .slide-img-wrap li {
float: left;
width: 500px;
}
.slideshow .slide-img-wrap li img {
width: 500px;
height: 300px;
}
/* 设置下一个和上一个的按钮 */
.slideshow .slide-btn-wrap {
position: absolute;
z-index: 100;
top: 50%;
left: 0;
width: 500px;
height: 30px;
margin-top: -15px;
}
.slideshow .slide-btn-wrap a {
color: #999;
font-size: 30px;
line-height: 30px;
font-weight: bold;
background-color: rgba(99, 99, 99, .5);
margin: 5px;
}
.slideshow .slide-btn-wrap a:hover {
background-color: rgba(99, 99, 99, .8);
}
.slideshow .slide-btn-wrap .next {
float: right;
}
.slideshow .slide-btn-wrap .prev {
float: left;
}
/* 设置圆点选择 */
.slideshow .slide-sel-btn {
position: absolute;
top: 80%;
left: 50%;
margin-left: -28px;
height: 10px;
width: 64 px;
z-index: 100;
}
.slideshow .slide-sel-btn a {
border-radius: 50%;
background-color: #fff;
width: 8px;
height: 8px;
margin-right: 8px;
float: left;
}
.slideshow .slide-sel-btn a.on {
background-color: #666;
}
</style>
</head>
<body>
<div class="slideshow">
<!-- 滑动的图片 -->
<ul class="slide-img-wrap">
<li index="0" class="on">
<a href="#">
<img src="../img/1.jpg" alt="">
</a>
</li>
<li index="1">
<a href="#">
<img src="../img/2.jpg" alt="">
</a>
</li>
<li index="2">
<a href="#">
<img src="../img/3.jpg" alt="">
</a>
</li>
<li index="3">
<a href="#">
<img src="../img/4.jpg" alt="">
</a>
</li>
</ul>
<!-- 上一张和下一张的按钮 -->
<div class="slide-btn-wrap">
<a href="javascript:0" class="prev"><</a>
<a href="javascript:0" class="next">></a>
</div>
<!-- 选择圆圈按钮 -->
<div class="slide-sel-btn">
<a index="0" class="on" href="javascript:0"></a>
<a index="1" href="javascript:0"></a>
<a index="2" href="javascript:0"></a>
<a index="3" href="javascript:0"></a>
</div>
</div>
<script>
// 实现第一张滑动到第二张
window.onload = function () {
// 下一个按钮
var btnNext = document.querySelector('.slide-btn-wrap .next');
btnNext.onclick = function (e) {
slideShowNext();
autoSlide();
};
// 上一个按钮
var btnPrev = document.querySelector('.slide-btn-wrap .prev');
btnPrev.onclick = function (e) {
slideShowPrev();
autoSlide();
};
// 具体选中圆圈的跳转的具体页面
var selBtnDiv = document.querySelector('.slide-sel-btn');
selBtnDiv.onclick = function (e) {
e = e || window.event;
var target = e.target || e.srcElement;
if (target == this) {
return;
}
// 如果是点击子元素 a标签
var nextIndex = target.getAttribute('index');
nextIndex = parseInt(nextIndex);
// 设置为on的样式类的a标签
var curA = document.querySelector('.slide-sel-btn .on');
var curIndex = curA.getAttribute('index');
var curIndex = parseInt(curIndex);
console.log('next:' + nextIndex + ' prev:' + curIndex)
slide(curIndex, nextIndex);
// 选中轮播后,要重新设置自动轮播 的时钟
autoSlide();
}
// 自动轮播
autoSlide();
};
// 执行下一张图片
function slideShowNext() {
// 滑动下一张图片
var curLi = document.querySelector('.slide-img-wrap .on');
var curIndex = curLi.getAttribute('index');
curIndex = parseInt(curIndex); // 0, 1, 2, 3
// 让索进行循环: 0,1,2,3,1,2,3,0,.....
var nextIndex = (curIndex + 1) % 4;
slide(curIndex, nextIndex);
}
function slideShowPrev() {
// 滑动下一张图片
var curLi = document.querySelector('.slide-img-wrap .on');
var curIndex = curLi.getAttribute('index');
curIndex = parseInt(curIndex); // 0, 1, 2, 3
// 让索进行循环: 0,1,2,3,1,2,3,0,.....
var nextIndex = (curIndex - 1 + 4) % 4;
slide(curIndex, nextIndex);
}
var timer;
// 自动轮播
function autoSlide() {
// 先去掉时钟。
if (timer) {
clearInterval(timer);
timer = null;
}
// 实现自动滚动效果。
timer = setInterval(function () {
slideShowNext();
}, 2000);
}
function slide(curIndex, nextIndex) {
// 0 left: 0
// 1 left: -500px
// 2 left: -1000px
// 3 lfet: -1500px
// 要让下一个图片的左放到盒子的最左侧。
var imgList = document.querySelector('.slide-img-wrap');
var nextLeft = nextIndex * (-500);
var curLeft = imgList.offsetLeft;
// imgList.style.left = (imgList.offsetLeft - 500) + 'px';
// imgList.style.left = nextLeft + 'px';
// 进行动画的轮播
slideAnimate(curLeft, nextLeft, imgList, 500);
// 把li标签和span标签的选中的那个标签的class的 on设置一下。
var liArray = document.querySelectorAll('.slide-img-wrap li');
liArray[curIndex].className = "";
liArray[nextIndex].className = "on";
// slide-sel-btn 下面的a标签 重新设置on
var slideSelBtnArray = document.querySelectorAll('.slide-sel-btn a');
slideSelBtnArray[curIndex].className = "";
slideSelBtnArray[nextIndex].className = "on";
}
// 对元素进行连续的滚动
function slideAnimate(curLeft, endLeft, element, duration) {
var w = endLeft - curLeft; // 总的滑动的距离
var wPerMS = w / duration; // 每毫秒需要移动的距离。
var startTime = Date.now();
var ainmateTimer = setInterval(function(){
var curTime = Date.now();
// 每一帧直接的时间间隔。
var delateTime = curTime - startTime;
element.style.left = (element.offsetLeft + delateTime * wPerMS ) + 'px';
duration = duration - delateTime;
if(duration <= 0) {
element.style.left = endLeft + 'px';
clearInterval(ainmateTimer);
return;
}
// 把当前时间设置成起始时间。
startTime = curTime;
}, 1000/60);
}
</script>
</body>
</html>
DOM特效封装 - 手风琴效果
案例:69-accordion手风琴
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>70-accordion手风琴.html</title>
<style>
html, body, div, ul, li {
margin: 0; padding: 0;
}
ul, ol {
list-style: none;
}
.ac {
border: 1px solid #ccc;
width: 300px;
margin: 100px auto;
}
.ac .ac-item .ac-item-hd {
height: 30px;
line-height: 30px;
background-color: #efefef;
border: 1px solid #ddd;
cursor: pointer;
}
.ac .ac-item .ac-item-bd {
display: none;
height: 150px;
}
.ac .on .ac-item-bd {
display: block;
}
</style>
</head>
<body>
<ul class="ac">
<li class="ac-item on">
<div class="ac-item-hd">头部1</div>
<div class="ac-item-bd">内容1</div>
</li>
<li class="ac-item">
<div class="ac-item-hd">头部2</div>
<div class="ac-item-bd">内容2</div>
</li>
<li class="ac-item">
<div class="ac-item-hd">头部3</div>
<div class="ac-item-bd">内容3</div>
</li>
<li class="ac-item">
<div class="ac-item-hd">头部4</div>
<div class="ac-item-bd">内容4</div>
</li>
</ul>
<script>
window.onload = function() {
var liArray = document.querySelectorAll('.ac-item');
for(var i = 0; i <liArray.length; i++) {
liArray[i].onclick = function(e) {
for(var j = 0; j < liArray.length; j++) {
liArray[j].className = "ac-item";
}
// li被点击后,自己要添加on样式类,所有的兄弟li都要去掉on样式类
this.className = "ac-item on";
};
}
};
</script>
</body>
</html>
表单验证
动态创建表格
案例:70-表单校验
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>表单校验</title>
</head>
<body>
<form id="frm" action="#">
<table>
<!-- <tr>
<td>html5 </td>
<td>
<input type="email" name="txtName" id="txtName">
<input type="number" name="txtName" id="txtName">
<input type="date" name="txtName" id="txtName">
</td>
</tr> -->
<tr>
<td>姓名:</td>
<td>
<input type="text" name="txtName" placeholder="文本不少于6个字符" id="txtName">
</td>
</tr>
<tr>
<td>邮箱</td>
<td><input type="text" name="txtEmail" id="txtEmail"></td>
</tr>
<tr>
<td>Tel</td>
<td><input type="text" name="txtTel" id="txtTel"></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="提交">
<input type="reset" value="重置">
</td>
</tr>
</table>
</form>
<script>
window.onload = function() {
// 拿到表单
var frm = document.getElementById('frm');
// var frm = document.forms[0];
// 用户名长度错误是提示的消息
var txtNameMsg = document.createElement('span');
txtNameMsg.innerHTML = "姓名的字符串长度必须在6-20之间";
txtNameMsg.style.color = "red";
// 表单提交的时候限制性此事件响应方法
frm.onsubmit = function(e) {
// console.log('frm submit')
// 校验用户名文本框的字符不少于6个字符,但不能多于20个字符
var txtName = document.getElementById('txtName');
// txtName.value;
var txtNameRegExp = /\w{6,20}/gi;
if(txtNameRegExp.test(txtName.value)) {
// 移除文本框错误消息
txtName.parentNode.removeChild(txtNameMsg);
} else {
// 校验失败,添加错误信息取消默认操作
txtName.parentNode.appendChild(txtNameMsg);
return false;
}
// e = e || window.event;
// // dom2级绑定事件的取消默认操作的用法
// if(e.preventDefault) {
// e.preventDefault();
// } else {
// e.returnValue = false;
// }
// // 只兼容dom0级绑定事件的方式
// return false;
};
}
</script>
</body>
</html>
源代码下载: https://github.com/godlikecheng/JavaScript_complete
上一篇: JS - BOM详解 -06
下一篇: 暂无.