模拟BootStrap的弹框功能

模拟BootStrap的弹框功能

今天项目中遇到了一个需要,需要用到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>我是弹框left</p>
            <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>我是弹框right</p>
            <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">A</option>
                    <option value="2">B</option>
                    <option value="3">C</option>
                </select>
            </div>
        </div>
        <div>
            <p>我是弹框top</p>
            <span class="btn" data-afaPOP_target="a3" data-afaPOP_direction="top">点击我</span>
            <div id="a3" data-popDiv>
                <p>JavaScript是世界上最好的语言</p>
            </div>
        </div>
        <div>
            <p>我是弹框bottom</p>
            <span class="btn" data-afaPOP_target="a4" data-afaPOP_direction="bottom">点击我</span>
            <div id="a4" data-popDiv>
                <ul>
                    <li>asd</li>
                    <li>asd</li>
                    <li>asd</li>
                    <li>asd</li>
                </ul>
            </div>
        </div>
    </div>

这里简单介绍一下对应的一些属性:

  • data-afaPOP_target - 指向弹框的id。
  • data-afaPOP_direction - 表示弹框的方向。
  • data-popDiv - 写在弹框对应的标签中,主要是给样式的。
  • data-afaClosePOP - 绑定点击后隐藏弹框的事件

暂时就这些属性去进行定义和绑定事件,因为项目中还没有发现需要补充的功能,所以暂时就这样了,当然以后有时间还是继续优化的。

其中还有一些BUG还没有时间去修改,但不影响使用…

现在把代码补全:

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <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>我是弹框left</p>
            <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>我是弹框right</p>
            <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">A</option>
                    <option value="2">B</option>
                    <option value="3">C</option>
                </select>
            </div>
        </div>
        <div>
            <p>我是弹框top</p>
            <span class="btn" data-afaPOP_target="a3" data-afaPOP_direction="top">点击我</span>
            <div id="a3" data-popDiv>
                <p>JavaScript是世界上最好的语言</p>
            </div>
        </div>
        <div>
            <p>我是弹框bottom</p>
            <span class="btn" data-afaPOP_target="a4" data-afaPOP_direction="bottom">点击我</span>
            <div id="a4" data-popDiv>
                <ul>
                    <li>asd</li>
                    <li>asd</li>
                    <li>asd</li>
                    <li>asd</li>
                </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 <popDivs.length;n++){
            popDivs[n].setAttribute('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,菜鸟一枚多多关注!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Bootstrap是一个流行的前端开发框架,它提供了丰富的组件和样式,可以帮助开发者快速构建响应式网页。其中,Bootstrap弹框是一种常用的交互组件,用于在页面上显示一些提示、警告或者用户交互的内容。 Bootstrap弹框有两种类型:模态框(Modal)和警告框(Alert)。模态框是一种覆盖在页面上的弹出窗口,可以用来显示详细信息、表单、图片等内容。警告框则是一种简单的提示框,用于显示警告、成功、错误等信息。 使用Bootstrap弹框需要引入Bootstrap的CSS和JavaScript文件,并按照一定的HTML结构和属性来定义弹框的内容和行为。以下是一个简单的示例: ```html <!-- 模态框示例 --> <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#myModal"> 打开模态框 </button> <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="myModalLabel">模态框标题</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> 模态框内容... </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button> <button type="button" class="btn btn-primary">保存</button> </div> </div> </div> </div> <!-- 警告框示例 --> <div class="alert alert-success" role="alert"> 这是一个成功的警告框。 </div> ``` 在上述示例中,模态框通过`data-toggle="modal"`和`data-target="#myModal"`来触发弹出,并使用`<div class="modal">`来定义模态框的结构。警告框则使用`<div class="alert">`来定义。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值