今天项目中遇到了一个需要,需要用到BootStrap的弹框功能,但因为考虑到日后可能需要改用AngularJS去进行开发,大家都知道AngularJS和BootStrap的js文件是有冲突,因为BootStrap的js文件是依赖与jQuery的,如果用AngularJS去开发,意味着需要连BootStrap都不能用,但可以用UI-BootStrap,但因为不太熟悉UI-BootStrap,不知道有没有封装到该功能,所以就打算自己写一个类似BootStrap的弹框的,顺便当锻炼以下自己,也未以后的模块化开发做做准备。废话不多说,进入主题。
首先是需要到两个文件,分别是一个js文件和css文件。
<link rel="stylesheet" href="../afa_pop/afa_pop.css">
<script src="../afa_pop/afa_pop.js">script>
因为我也的插件不依赖任何第三方插件,是原生去写的,所以应该兼容性会比较好吧。
然后调用方式:
<div class="list">
<div>
<p>我是弹框leftp>
<span class="btn" id="a" data-afaPOP_target="a1" data-afaPOP_direction="left">点击我span>
<div id="a1" data-popDiv>
<input type="text">
<button>确定button>
div>
div>
<div>
<p>我是弹框rightp>
<span class="btn" data-afaPOP_target="a2" data-afaPOP_direction="right">点击我span>
<div id="a2" data-popDiv>
<select>
<option value="0">请选择option>
<option value="1">Aoption>
<option value="2">Boption>
<option value="3">Coption>
select>
div>
div>
<div>
<p>我是弹框topp>
<span class="btn" data-afaPOP_target="a3" data-afaPOP_direction="top">点击我span>
<div id="a3" data-popDiv>
<p>JavaScript是世界上最好的语言p>
div>
div>
<div>
<p>我是弹框bottomp>
<span class="btn" data-afaPOP_target="a4" data-afaPOP_direction="bottom">点击我span>
<div id="a4" data-popDiv>
<ul>
<li>asdli>
<li>asdli>
<li>asdli>
<li>asdli>
ul>
div>
div>
div>
这里简单介绍一下对应的一些属性:
暂时就这些属性去进行定义和绑定事件,因为项目中还没有发现需要补充的功能,所以暂时就这样了,当然以后有时间还是继续优化的。
其中还有一些BUG还没有时间去修改,但不影响使用…
现在把代码补全:
html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<link rel="stylesheet" href="../afa_pop/afa_pop.css">
<style>
.list{
height:800px;
width: 50%;
overflow-y:auto;
border:1px solid #e1e1e1;
text-align: center;
margin:0 auto;
}
.list>div{
border-bottom:1px solid #000;
padding:5px;
}
style>
head>
<body>
<div class="list">
<div>
<p>我是弹框leftp>
<span class="btn" id="a" data-afaPOP_target="a1" data-afaPOP_direction="left">点击我span>
<div id="a1" data-popDiv>
<input type="text">
<button>确定button>
div>
div>
<div>
<p>我是弹框rightp>
<span class="btn" data-afaPOP_target="a2" data-afaPOP_direction="right">点击我span>
<div id="a2" data-popDiv>
<select>
<option value="0">请选择option>
<option value="1">Aoption>
<option value="2">Boption>
<option value="3">Coption>
select>
div>
div>
<div>
<p>我是弹框topp>
<span class="btn" data-afaPOP_target="a3" data-afaPOP_direction="top">点击我span>
<div id="a3" data-popDiv>
<p>JavaScript是世界上最好的语言p>
div>
div>
<div>
<p>我是弹框bottomp>
<span class="btn" data-afaPOP_target="a4" data-afaPOP_direction="bottom">点击我span>
<div id="a4" data-popDiv>
<ul>
<li>asdli>
<li>asdli>
<li>asdli>
<li>asdli>
ul>
div>
div>
div>
body>
<script src="../afa_pop/afa_pop.js">script>
html>
css
*[data-popDiv]{visibility:hidden;background-color:#fff;border:2px solid #000;border-radius: 5px;position:absolute;z-index: 9999;padding: 12px;}
*[data-popDiv] .horn{display: block;position: absolute;width: 15px;height: 15px;z-index: 9999;background-color: #fff;-webkit-transform: rotate(-45deg);}
*[data-popDiv] .horn_left{border-bottom: 2px solid #000;border-right: 2px solid #000;}
*[data-popDiv] .horn_right{border-top: 2px solid #000;border-left: 2px solid #000;}
*[data-popDiv] .horn_top{border-top: 2px solid #000;border-right: 2px solid #000;}
*[data-popDiv] .horn_bottom{border-bottom: 2px solid #000;border-left: 2px solid #000;}
*[data-hasShowPOP = 'true']{visibility:visible;animation: afa_showPOP 0.5s;-moz-animation: afa_showPOP 0.5s;-webkit-animation: afa_showPOP 0.5s;-o-animation: afa_showPOP 0.5s;}
*[data-hasShowPOP = 'false']{visibility:hidden;animation: afa_hidePOP 0.5s;-moz-animation: afa_hidePOP 0.5s;-webkit-animation: afa_hidePOP 0.5s;-o-animation: afa_hidePOP 0.5s;}
#afa_pop_mask{top: 0;left: 0;position:fixed;width: 100%;height: 100%;z-index: 999;}
/*显示*/
@keyframes afa_showPOP
{
from {
filter:alpha(opacity=0);
-moz-opacity:0;
opacity:0;
}
to {
filter:alpha(opacity=100);
-moz-opacity:1;
opacity:1;
}
}
@-moz-keyframes afa_showPOP /* Firefox */
{
from {
filter:alpha(opacity=0);
-moz-opacity:0;
opacity:0;
}
to {
filter:alpha(opacity=100);
-moz-opacity:1;
opacity:1;
}
}
@-webkit-keyframes afa_showPOP /* Safari 和 Chrome */
{
from {
filter:alpha(opacity=0);
-moz-opacity:0;
opacity:0;
}
to {
filter:alpha(opacity=100);
-moz-opacity:1;
opacity:1;
}
}
@-o-keyframes afa_showPOP /* Opera */
{
from {
filter:alpha(opacity=0);
-moz-opacity:0;
opacity:0;
}
to {
filter:alpha(opacity=100);
-moz-opacity:1;
opacity:1;
}
}
/*隐藏*/
@keyframes afa_hidePOP
{
from {
filter:alpha(opacity=100);
-moz-opacity:1;
opacity:1;
}
to {
filter:alpha(opacity=0);
-moz-opacity:0;
opacity:0;
}
}
@-moz-keyframes afa_hidePOP /* Firefox */
{
from {
filter:alpha(opacity=100);
-moz-opacity:1;
opacity:1;
}
to {
filter:alpha(opacity=0);
-moz-opacity:0;
opacity:0;
}
}
@-webkit-keyframes afa_hidePOP /* Safari 和 Chrome */
{
from {
filter:alpha(opacity=100);
-moz-opacity:1;
opacity:1;
}
to {
filter:alpha(opacity=0);
-moz-opacity:0;
opacity:0;
}
}
@-o-keyframes afa_hidePOP /* Opera */
{
from {
filter:alpha(opacity=100);
-moz-opacity:1;
opacity:1;
}
to {
filter:alpha(opacity=0);
-moz-opacity:0;
opacity:0;
}
}
js
/**
* Created by Administrator on 2016/5/3.
*/
window.onload = function(){
//尖角的宽高,如果改变尖角宽高需要css和js同时去更改
var hornHeight = 19,
hornWidth = 19,
scrollTop = 0,
scrollLeft = 0;
//初始化
function init(){
var afaPOPs = document.querySelectorAll('[data-afaPOP_target]');
var afaClose = document.querySelectorAll('[data-afaClosePOP]');
//循环设定位置及绑定显示隐藏事件
for(var i = 0;i < afaPOPs.length;i++){
var curr = afaPOPs[i],
targetId = curr.dataset.afapop_target,
direction = curr.dataset.afapop_direction;
//设置尖角的位置和弹框的定位
switch (direction){
case 'left' : setPOPDirection.left(document.getElementById(targetId));
setPosition.left(curr,document.getElementById(targetId));
break;
case 'right' : setPOPDirection.right(document.getElementById(targetId));
setPosition.right(curr,document.getElementById(targetId));
break;
case 'top' : setPOPDirection.top(document.getElementById(targetId));
setPosition.top(curr,document.getElementById(targetId));
break;
case 'bottom' : setPOPDirection.bottom(document.getElementById(targetId));
setPosition.bottom(curr,document.getElementById(targetId));
break;
}
//绑定事件
!function(targetId,curr,direction){
curr.addEventListener('click',function(){
//隐藏弹框
if(document.getElementById(targetId).getAttribute('data-hasShowPOP') == 'true'){
var mask = document.getElementById('afa_pop_mask');
if(mask){
document.body.removeChild(mask);
}
document.getElementById(targetId).setAttribute('data-hasShowPOP','false');
//显示弹框
}else{
//先隐藏所有弹框
closeAllPOP(function(){
//设置尖角的位置和弹框的定位
switch (direction){
case 'left' : setPosition.left(curr,document.getElementById(targetId));
break;
case 'right' : setPosition.right(curr,document.getElementById(targetId));
break;
case 'top' : setPosition.top(curr,document.getElementById(targetId));
break;
case 'bottom' : setPosition.bottom(curr,document.getElementById(targetId));
break;
}
//先创建一个mask
var mask = document.createElement('div');
mask.id = 'afa_pop_mask';
document.body.appendChild(mask);
//点击mask隐藏元素,模拟点击body
document.getElementById('afa_pop_mask').addEventListener('click',function(){
//隐藏完后删除mask
closeAllPOP(function(){
document.body.removeChild(mask);
});
});
//显示对应弹框
document.getElementById(targetId).setAttribute('data-hasShowPOP','true');
});
}
});
}(targetId,curr,direction);
}
//循环绑定隐藏事件
for(var n = 0;n < afaClose.length;n++){
closePOP(afaClose[n]);
}
}
//关闭所有弹框
function closeAllPOP(callback){
var popDivs = document.querySelectorAll('[data-popDiv]');
for(var n =0;n 'data-hasShowPOP','false');
}
if(callback){
callback();
}
}
//关闭弹框事件
function closePOP(curr){
var id = curr.dataset.afaclosepop;
curr.addEventListener('click',function(){
document.getElementById(id).setAttribute('data-hasShowPOP','false');
})
}
//设置尖角的位置和方向
var setPOPDirection = {
left : function(elem){
var popHeight = elem.offsetHeight,
popWidth = elem.offsetWidth,
horn = document.createElement('span');
horn.className = 'horn horn_left';
elem.appendChild(horn);
horn.style.top = (popHeight/2 - hornHeight/2) + 'px';
horn.style.left = (popWidth - hornWidth/2)-1 + 'px';
},
right : function(elem){
var popHeight = elem.offsetHeight,
horn = document.createElement('span');
horn.className = 'horn horn_right';
elem.appendChild(horn);
horn.style.top = (popHeight/2 - hornHeight/2) + 'px';
horn.style.left = (0 - hornWidth/2) + 'px';
},
bottom : function(elem){
var popWidth = elem.offsetWidth,
horn = document.createElement('span');
horn.className = 'horn horn_top';
elem.appendChild(horn);
horn.style.top = (0 - hornWidth/2) + 'px';
horn.style.left = (popWidth/2 - hornWidth/2) + 'px';
},
top : function(elem){
var popHeight = elem.offsetHeight,
popWidth = elem.offsetWidth,
horn = document.createElement('span');
horn.className = 'horn horn_bottom';
elem.appendChild(horn);
horn.style.top = (popHeight - hornWidth/2) - 2 + 'px';
horn.style.left = (popWidth/2 - hornWidth/2) + 'px';
}
};
//设置弹框的位置
var setPosition = {
left : function(curr,elem){
var elemHeight = elem.offsetHeight,
elemWidth = elem.offsetWidth,
currHeight = curr.offsetHeight,
currX = curr.offsetLeft,
currY = curr.offsetTop,
parentScrollTop = getTop(curr),
parentScrollLeft = getLeft(curr);
elem.style.left = currX - elemWidth - hornWidth - parentScrollLeft + 'px';
elem.style.top = currY - elemHeight/2 + currHeight/2 - parentScrollTop + 'px';
//归零
scrollTop = 0;
scrollLeft = 0;
},
right : function(curr,elem){
var elemHeight = elem.offsetHeight,
currHeight = curr.offsetHeight,
currWidth = curr.offsetWidth,
currX = curr.offsetLeft,
currY = curr.offsetTop,
parentScrollTop = getTop(curr),
parentScrollLeft = getLeft(curr);
elem.style.left = currX + currWidth + hornWidth + -parentScrollLeft + 'px';
elem.style.top = currY - elemHeight/2 + currHeight/2 - parentScrollTop + 'px';
//归零
scrollTop = 0;
scrollLeft = 0;
},
bottom : function(curr,elem){
var currHeight = curr.offsetHeight,
elemWidth = elem.offsetWidth,
currWidth = curr.offsetWidth,
currX = curr.offsetLeft,
currY = curr.offsetTop,
parentScrollTop = getTop(curr),
parentScrollLeft = getLeft(curr);
elem.style.left = currX - elemWidth/2 + currWidth/2 - parentScrollLeft + 'px';
elem.style.top = currY + currHeight + hornHeight - parentScrollTop + 'px';
//归零
scrollTop = 0;
scrollLeft = 0;
},
top : function(curr,elem){
var elemHeight = elem.offsetHeight,
elemWidth = elem.offsetWidth,
currWidth = curr.offsetWidth,
currX = curr.offsetLeft,
currY = curr.offsetTop,
parentScrollTop = getTop(curr),
parentScrollLeft = getLeft(curr);
elem.style.left = currX - elemWidth/2 + currWidth/2 - parentScrollLeft + 'px';
elem.style.top = currY - elemHeight - hornHeight - parentScrollTop + 'px';
//归零
scrollTop = 0;
scrollLeft = 0;
}
};
/*
* 当父元素有可能有scrollTop和scrollLeft的时候会影响定位
* 所以需要进行递归处理,计算当前所有父元素的scrollTop和scrollLeft
* 最后再修正定位,保持始终是相对与窗口左上角进行定位
*
* */
function getTop(e){
if(e.parentNode != null){
var scroll = e.parentNode.scrollTop;
scroll = scroll == undefined ? 0 : scroll;
scrollTop += scroll;
getTop(e.parentNode);
}
return scrollTop;
}
function getLeft(e){
if(e.parentNode != null){
var scroll = e.parentNode.scrollLeft;
scroll = scroll == undefined ? 0 : scroll;
scrollLeft += scroll;
getTop(e.parentNode);
}
return scrollLeft;
}
//页面加载完时自动执行
init();
//页面大小改变时重新计算
window.addEventListener('resize',function(){
init();
});
};
如果有兴趣一起谈讨互相学习的欢迎留言,一起改改BUG,菜鸟一枚多多关注!