前面的话

  在 Bootstrap 框架中把模态弹出框统一称为 Modal。这种弹出框效果在大多数 Web 网站的交互中都可见。比如点击一个按钮弹出一个框,弹出的框可能是一段文件描述,也可能带有按钮操作,也有可能弹出的是一张图片。本文将详细介绍Bootstrap模态弹出框

结构分析

  Bootstrap框架中的模态弹出框,分别运用了“modal”、“modal-dialog”和“modal-content”样式,而弹出窗真正的内容都放置在“modal-content”中,其主要又包括三个部分:

  ☑ 弹出框头部,一般使用“modal-header”表示,主要包括标题和关闭按钮

  ☑ 弹出框主体,一般使用“modal-body”表示,弹出框的主要内容

  ☑ 弹出框脚部,一般使用“modal-footer”表示,主要放置操作按钮

  1. <div class="modal show">
  2. <div class="modal-dialog">
  3. <div class="modal-content">
  4. <div class="modal-header">
  5. <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
  6. <h4 class="modal-title">模态弹出窗标题</h4>
  7. </div>
  8. <div class="modal-body">
  9. <p>模态弹出窗主体内容</p>
  10. </div>
  11. <div class="modal-footer">
  12. <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
  13. <button type="button" class="btn btn-primary">保存</button>
  14. </div>
  15. </div><!-- /.modal-content -->
  16. </div><!-- /.modal-dialog -->
  17. </div><!-- /.modal -->

  对于弹窗而言,modal-content是样式的关键。主要设置了弹窗的边框、边距、背景色和阴影等样式

  1. .modal-content {
  2. position: relative;
  3. background-color: #fff;
  4. -webkit-background-clip: padding-box;
  5. background-clip: padding-box;
  6. border: 1px solid #999;
  7. border: 1px solid rgba(0, 0, 0, .2);
  8. border-radius: 6px;
  9. outline:;
  10. -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5);
  11. box-shadow: 0 3px 9px rgba(0, 0, 0, .5);
  12. }

  除此之外,modal-content中的modal-header、modal-body和modal-footer三个部分样式设置如下

  1. .modal-header {
  2. min-height: 16.42857143px;
  3. padding: 15px;
  4. border-bottom: 1px solid #e5e5e5;
  5. }
  6. .modal-header .close {
  7. margin-top: -2px;
  8. }
  9. .modal-title {
  10. margin:;
  11. line-height: 1.42857143;
  12. }
  13. .modal-body {
  14. position: relative;
  15. padding: 15px;
  16. }
  17. .modal-footer {
  18. padding: 15px;
  19. text-align: right;
  20. border-top: 1px solid #e5e5e5;
  21. }

  这三个部分主要控制一些间距的样式。而modal-footer都是用来放置按钮,所以底部还对包含的按钮做了一定的样式处理

  1. .modal-footer .btn + .btn {
  2. margin-bottom:;
  3. margin-left: 5px;
  4. }
  5. .modal-footer .btn-group .btn + .btn {
  6. margin-left: -1px;
  7. }
  8. .modal-footer .btn-block + .btn-block {
  9. margin-left:;
  10. }

触发方式

  众所周知,模态弹出窗在页面加载完成时,是被隐藏在页面中的,只有通过一定的动作(事件)才能触发模态弹出窗的显示。在Bootstrap框架中实现方法有2种

  在介绍触发方式之前,首先要说明.show和.fade这两个方法。只有模态弹出窗默认是隐藏的,才能触发其显示

  1. .fade {
  2. opacity:;
  3. -webkit-transition: opacity .15s linear;
  4. -o-transition: opacity .15s linear;
  5. transition: opacity .15s linear;
  6. }
  7. .show {
  8. display: block!important;
  9. }

【方法一】

  模态弹出窗声明,只需要自定义两个必要的属性:data-toggle和data-target(bootstrap中声明式触发方法一般依赖于这些自定义的data-xxx 属性。比如data-toggle="" 或者 data-dismiss="")

  data-toggle必须设置为modal(toggle中文翻译过来就是触发器);

  data-target可以设置为CSS的选择符,也可以设置为模态弹出窗的ID值,一般情况设置为模态弹出窗的ID值,因为ID值是唯一的值

  1. <!-- 触发模态弹出窗的元素 -->
  2. <button type="button" data-toggle="modal" data-target="#mymodal" class="btn btn-primary">点击</button>
  3. <!-- 模态弹出窗 -->
  4. <div class="modal fade" id="mymodal">
  5. <div class="modal-dialog">
  6. <div class="modal-content">
  7. <div class="modal-header">
  8. <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
  9. <h4 class="modal-title">模态弹出窗标题</h4>
  10. </div>
  11. <div class="modal-body">
  12. <p>模态弹出窗主体内容</p>
  13. </div>
  14. <div class="modal-footer">
  15. <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
  16. <button type="button" class="btn btn-primary">保存</button>
  17. </div>
  18. </div><!-- /.modal-content -->
  19. </div><!-- /.modal-dialog -->
  20. </div><!-- /.modal -->

【方法二】

  触发模态弹出窗也可以是一个链接<a>元素,那么可以使用链接元素自带的href属性替代data-target属性

  不过建议还是使用统一使用data-target的方式来触发

  1. <!-- 触发模态弹出窗的元素 -->
  2. <a data-toggle="modal" href="#mymodal" class=" btn btn-primary" >点击</a>
  3. <!-- 模态弹出窗 -->
  4. <div class="modal fade" id="mymodal">
  5. <div class="modal-dialog">
  6. <div class="modal-content">
  7. <div class="modal-header">
  8. <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
  9. <h4 class="modal-title">模态弹出窗标题</h4>
  10. </div>
  11. <div class="modal-body">
  12. <p>模态弹出窗主体内容</p>
  13. </div>
  14. <div class="modal-footer">
  15. <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
  16. <button type="button" class="btn btn-primary">保存</button>
  17. </div>
  18. </div><!-- /.modal-content -->
  19. </div><!-- /.modal-dialog -->
  20. </div><!-- /.modal -->

尺寸

  Bootstrap框架为模态弹出窗提供了不同尺寸,一个是大尺寸样式“modal-lg”,另一个是小尺寸样式“modal-sm”。其结构上稍做调整

  [注意].bs-example-modal-lg和.bs-example-modal-sm是自定义的名称,而非必须

  1. <!-- 大尺寸模态弹出窗 -->
  2. <div class="modal fade bs-example-modal-lg" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" aria-hidden="true">
  3. <div class="modal-dialog modal-lg">
  4. <div class="modal-content"> ... </div>
  5. </div>
  6. </div>
  7. <!-- 小尺寸模态弹出窗 -->
  8. <div class="modal fade bs-example-modal-sm" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
  9. <div class="modal-dialog modal-sm">
  10. <div class="modal-content"> ... </div>
  11. </div>
  12. </div>
  1. <button type="button" class="btn btn-primary" data-toggle="modal" data-target=".bs-example-modal-lg">大尺寸</button>
  2. <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#myModal">默认尺寸</button>
  3. <button type="button" class="btn btn-primary" data-toggle="modal" data-target=".bs-example-modal-sm">小尺寸</button>
  4.  
  5. <div class="modal fade" id="myModal">
  6. <div class="modal-dialog">
  7. <div class="modal-content">
  8. <div class="modal-body">
  9. <p>小火柴的蓝色理想</p>
  10. </div>
  11. </div>
  12. </div>
  13. </div>
  14. <div class="modal fade bs-example-modal-lg">
  15. <div class="modal-dialog modal-lg">
  16. <div class="modal-content">
  17. <div class="modal-body">
  18. <p>小火柴的蓝色理想</p>
  19. </div>
  20. </div>
  21. </div>
  22. </div>
  23. <div class="modal fade bs-example-modal-sm">
  24. <div class="modal-dialog modal-sm">
  25. <div class="modal-content">
  26. <div class="modal-body">
  27. <p>小火柴的蓝色理想</p>
  28. </div>
  29. </div>
  30. </div>
  31. </div>

CSS解析

  bootstrap中的“模态弹出框”有以下几个特点:

  1、模态弹出窗是固定在浏览器中的。

  2、单击右侧全屏按钮,在全屏状态下,模态弹出窗宽度是自适应的,而且modal-dialog水平居中。

  3、当浏览器视窗大于768px时,模态弹出窗的宽度为600px

  4、模态弹出窗的背景常常有一个透明的蒙层效果

  5、触发弹窗时,弹窗是从上到下、逐渐浮现到页面前的

【固定在浏览器实现】

  1. .modal {
  2. position: fixed;
  3. top:;
  4. right:;
  5. bottom:;
  6. left:;
  7. z-index:;
  8. display: none;
  9. overflow: hidden;
  10. -webkit-overflow-scrolling: touch;
  11. outline:;
  12. }

【水平居中实现】

  1. .modal-dialog {
  2. position: relative;
  3. width: auto;
  4. margin: 10px;
  5. }

【当浏览器视窗大于768px时,模态弹出窗的宽度为600px实现】

  1. @media (min-width: 768px) {
  2. .modal-dialog {
  3. width: 600px;
  4. margin: 30px auto;
  5. }
  6. .modal-content {
  7. -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5);
  8. box-shadow: 0 5px 15px rgba(0, 0, 0, .5);
  9. }
  10. .modal-sm {
  11. width: 300px;
  12. }
  13. }

【蒙版】

  弹窗弹出时为 <body> 元素添加 .modal-open类,从而覆盖页面默认的滚动行为,并且还会自动生成一个 .modal-backdrop 元素用于提供一个可点击的区域,点击此区域就即可关闭模态框

  1. .modal-open {
  2. overflow: hidden;
  3. }
  1. .modal-backdrop {
  2. position: fixed;
  3. top:;
  4. right:;
  5. bottom:;
  6. left:;
  7. z-index:;
  8. background-color: #000;
  9. }

  给其添加了一个过渡动画,从fade到in,把opacity值从0变成了0.5

  1. .modal-backdrop.fade {
  2. filter: alpha(opacity=0);
  3. opacity:;
  4. }
  5. .modal-backdrop.in {
  6. filter: alpha(opacity=50);
  7. opacity: .5;
  8. }

【动画效果】

  弹窗的动画内容是从-25%的top值位置到top:0的位置

  1. .modal.fade .modal-dialog {
  2. -webkit-transition: -webkit-transform .3s ease-out;
  3. -o-transition: -o-transform .3s ease-out;
  4. transition: transform .3s ease-out;
  5. -webkit-transform: translate3d(0, -25%, 0);
  6. -o-transform: translate3d(0, -25%, 0);
  7. transform: translate3d(0, -25%, 0);
  8. }
  9.  
  10. .modal.in .modal-dialog {
  11. -webkit-transform: translate3d(0, 0, 0);
  12. -o-transform: translate3d(0, 0, 0);
  13. transform: translate3d(0, 0, 0);
  14. }

  如果不需要模态框弹出时的动画效果(淡入淡出效果),删掉 .fade 类即可

  1. <!-- 触发模态弹出窗的元素 -->
  2. <button type="button" data-toggle="modal" data-target="#mymodal" class="btn btn-primary">点击</button>
  3. <!-- 模态弹出窗 -->
  4. <div class="modal" id="mymodal">
  5. <div class="modal-dialog">
  6. <div class="modal-content">
  7. <div class="modal-header">
  8. <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
  9. <h4 class="modal-title">模态弹出窗标题</h4>
  10. </div>
  11. <div class="modal-body">
  12. <p>模态弹出窗主体内容</p>
  13. </div>
  14. <div class="modal-footer">
  15. <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
  16. <button type="button" class="btn btn-primary">保存</button>
  17. </div>
  18. </div><!-- /.modal-content -->
  19. </div><!-- /.modal-dialog -->
  20. </div><!-- /.modal -->

参数说明

  除了通过data-toggle和data-target来控制模态弹出窗之外,Bootstrap框架针对模态弹出框还提供了其他自定义data-属性,来控制模态弹出窗。有关Modal弹出窗自定义属性相关说明如下所示

  该参数设置在按钮上,或者弹窗上都可以。出于方便,一般地,在按钮上设置

  [注意]属性值一定要加引号,如data-backdrop="false"

  如果想要支持esc键关闭弹窗,需要在弹窗上设置tabindex="-1"

  1. <button type="button" data-toggle="modal" data-target="#mymodal1" class="btn btn-primary">默认样式</button>
  2. <button type="button" data-toggle="modal" data-target="#mymodal2" data-backdrop="false" class="btn btn-primary">无蒙版</button>
  3. <button type="button" data-toggle="modal" data-target="#mymodal3" data-keyboard="false" class="btn btn-primary">ESC失效</button>
  4. <button type="button" data-toggle="modal" data-target="#mymodal4" data-show="false" class="btn btn-primary">弹窗默认不显示</button>
  5.  
  6. <div class="modal fade" tabindex="-1" id="mymodal1">
  7. <div class="modal-dialog">
  8. <div class="modal-content">
  9. <div class="modal-header">
  10. <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
  11. <h4 class="modal-title">小火柴的蓝色理想</h4>
  12. </div>
  13. <div class="modal-body">
  14. <p>好的代码像粥一样,都是用时间熬出来的</p>
  15. </div>
  16. </div>
  17. </div>
  18. </div>
  19. <div class="modal fade" tabindex="-1" id="mymodal2">
  20. <div class="modal-dialog">
  21. <div class="modal-content">
  22. <div class="modal-header">
  23. <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
  24. <h4 class="modal-title">小火柴的蓝色理想</h4>
  25. </div>
  26. <div class="modal-body">
  27. <p>好的代码像粥一样,都是用时间熬出来的</p>
  28. </div>
  29. </div>
  30. </div>
  31. </div>
  32. <div class="modal fade" tabindex="-1" id="mymodal3">
  33. <div class="modal-dialog">
  34. <div class="modal-content">
  35. <div class="modal-header">
  36. <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
  37. <h4 class="modal-title">小火柴的蓝色理想</h4>
  38. </div>
  39. <div class="modal-body">
  40. <p>好的代码像粥一样,都是用时间熬出来的</p>
  41. </div>
  42. </div>
  43. </div>
  44. </div>
  45. <div class="modal fade" tabindex="-1" id="mymodal4">
  46. <div class="modal-dialog">
  47. <div class="modal-content">
  48. <div class="modal-header">
  49. <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
  50. <h4 class="modal-title">小火柴的蓝色理想</h4>
  51. </div>
  52. <div class="modal-body">
  53. <p>好的代码像粥一样,都是用时间熬出来的</p>
  54. </div>
  55. </div>
  56. </div>
  57. </div>

JS触发

  除了使用自定义属性data-触发模态弹出框之外,还可以通过JavaScript方法来触发模态弹出窗。比如说给按钮设置一个单击事件,然后触发模态弹出窗

  只需一行 JavaScript 代码,即可通过元素的 id myModal 调用模态框

  1. $('#myModal').modal()
  1. <button type="button" class="btn btn-primary">点击</button>
  2. <div class="modal fade" tabindex="-1" id="mymodal">
  3. <div class="modal-dialog">
  4. <div class="modal-content">
  5. <div class="modal-header">
  6. <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
  7. <h4 class="modal-title">小火柴的蓝色理想</h4>
  8. </div>
  9. <div class="modal-body">
  10. <p>好的代码像粥一样,都是用时间熬出来的</p>
  11. </div>
  12. </div>
  13. </div>
  14. </div>
  15. <script>
  16. $(function(){
  17. $(".btn").click(function(){
  18. $("#mymodal").modal();
  19. });
  20. });
  21. </script>

  使用JavaScript触发模态弹出窗时,Bootstrap框架提供了一些设置,主要包括属性设置、参数设置和事件设置

【属性设置】

  模态弹出窗默认支持的自定义属性主要有

  不想让用户按ESC键关闭模态弹出窗,可以这样做

  1. $(function(){
  2. $(".btn").click(function(){
  3. $("#mymodal").modal({
  4. keyboard:false
  5. });
  6. });
  7. });

【参数设置】

  在Bootstrap框架中还为模态弹出窗提供了三种参数设置,具体说明如下

  1. <button type="button" class="btn btn-primary" id="btn" style="position:absolute;z-index:9999">打开(关闭)</button>
  2. <div class="modal" tabindex="-1" id="mymodal" >
  3. <div class="modal-dialog">
  4. <div class="modal-content">
  5. <div class="modal-header">
  6. <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
  7. <h4 class="modal-title">小火柴的蓝色理想</h4>
  8. </div>
  9. <div class="modal-body">
  10. <p>好的代码像粥一样,都是用时间熬出来的</p>
  11. </div>
  12. </div>
  13. </div>
  14. </div>
  15. <script>
  16. ;$(function(){
  17. $("#btn").click(function(){
  18. $("#mymodal").modal("toggle");
  19. });
  20. });
  21. </script>

【事件设置】

  模态弹窗还支持五种类型的事件,分别是模态弹出窗的弹出前、弹出后,关闭前、关闭后及远端数据加载后,具体描述如下:

  1. <button type="button" class="btn btn-primary" id="btn" style="position:absolute;z-index:9999">打开</button>
  2. <div class="modal" tabindex="-1" id="mymodal" >
  3. <div class="modal-dialog">
  4. <div class="modal-content">
  5. <div class="modal-header">
  6. <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
  7. <h4 class="modal-title">小火柴的蓝色理想</h4>
  8. </div>
  9. <div class="modal-body">
  10. <p>好的代码像粥一样,都是用时间熬出来的</p>
  11. </div>
  12. </div>
  13. </div>
  14. </div>
  15. <script>
  16. ;$(function(){
  17. $("#btn").click(function(){
  18. $("#mymodal").modal("toggle");
  19. });
  20. $('#mymodal').on('hide.bs.modal', function(){
  21. $("#btn").html("打开");
  22. });
  23. $('#mymodal').on('show.bs.modal', function(){
  24. $("#btn").html("关闭");
  25. });
  26. });
  27. </script>

JS解析

【1】IIFE

  使用立即调用函数,防止插件内代码外泄,从而形成一个闭环,并且只能从jQuery的fn里进行扩展

  1. +function ($) {
  2. //使用es5严格模式
  3. 'use strict';
  4. //
  5. }(window.jQuery);

【2】初始设置

  1. var Modal = function (element, options) {
  2.  
  3. this.options = options//options是设置选项
  4. this.$body = $(document.body)//body元素
  5. this.$element = $(element)////element表示modal弹出框容器及内容元素
  6. this.$dialog = this.$element.find('.modal-dialog')//弹窗对象
  7. this.$backdrop = null //蒙版对象
  8. this.isShown = null //弹窗是否显示的标识
  9. this.originalBodyPad = null //body的padding-right标识
  10. this.scrollbarWidth = 0 //滚动条宽度为0
  11. this.ignoreBackdropClick = false //默认蒙板可点击
  12.  
  13. //如果设置了remote,就加载remote指定url的内容到modal-content样式的元素内,并触发loaded.bs.modal事件
  14. if (this.options.remote) {
  15. this.$element
  16. .find('.modal-content')
  17. .load(this.options.remote, $.proxy(function () {
  18. this.$element.trigger('loaded.bs.modal')
  19. }, this))
  20. }
  21. }
  22. //组件版本号3.3.7
  23. Modal.VERSION = '3.3.7'
  24.  
  25. //动画持续时间300ms
  26. Modal.TRANSITION_DURATION = 300
  27. //蒙版动画持续时间150ms
  28. Modal.BACKDROP_TRANSITION_DURATION = 150
  29.  
  30. //默认设置
  31. Modal.DEFAULTS = {
  32. backdrop: true, //显示蒙版
  33. keyboard: true, //按ESC键关闭弹窗
  34. show: true //单击触发元素时打开弹窗
  35. }

【3】插件核心代码

  主要是Modal核心类函数的定义、默认参数的定义和9个原型方法的定义,这9个原型方法主要是处理弹窗的反转、打开、关闭和弹窗背景设置、取消等操作

  1. // 反转弹窗(打开或关闭)
  2. Modal.prototype.toggle = function (_relatedTarget) {
  3. //如果弹窗处于显示状态,则调用hide()方法,关闭它;否则,调用show()方法,打开弹窗
  4. return this.isShown ? this.hide() : this.show(_relatedTarget)
  5. }
  6.  
  7. // 打开弹窗
  8. Modal.prototype.show = function (_relatedTarget) {
  9. //保存this值
  10. var that = this
  11. //定义弹窗前的触发事件
  12. var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
  13. //打开弹窗前,触发事件
  14. this.$element.trigger(e)
  15. // 如果已经打开了(或者曾经被阻止过),则退出执行,后续代码不做处理
  16. if (this.isShown || e.isDefaultPrevented()) return
  17. //设置弹窗显示标识为true
  18. this.isShown = true
  19. this.checkScrollbar()
  20. this.setScrollbar()
  21. this.$body.addClass('modal-open')
  22. //处理键盘事件,主要是设置按esc键时是否关闭弹窗
  23. this.escape()
  24. this.resize()
  25. // 如果单击了元素内的子元素(带有[data-dismiss="modal"]属性),则关闭弹窗
  26. this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
  27. //点击弹窗时,如果鼠标的目标是当前弹窗,则将默认蒙板不可点击的标识置为true,并不可再设置
  28. this.$dialog.on('mousedown.dismiss.bs.modal', function () {
  29. that.$element.one('mouseup.dismiss.bs.modal', function (e) {
  30. if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true
  31. })
  32. })
  33. //绘制蒙版后,处理以下代码
  34. this.backdrop(function () {
  35. // 判断浏览器是否支持动画,并且弹窗是否设置了动画过渡效果(是否有fade样式)
  36. var transition = $.support.transition && that.$element.hasClass('fade')
  37. // 如果modal弹窗没有父容器,则将它附加到body上
  38. if (!that.$element.parent().length) {
  39. that.$element.appendTo(that.$body)
  40. }
  41. // 显示modal弹窗
  42. that.$element
  43. .show()
  44. .scrollTop(0)
  45. that.adjustDialog()
  46. // 如果支持动画,强制刷新UI现场,重绘弹窗
  47. if (transition) {
  48. that.$element[0].offsetWidth
  49. }
  50. // 给modal弹窗添加in样式,和modal样式一起
  51. that.$element.addClass('in')
  52. // 强制给弹窗设定焦点
  53. that.enforceFocus()
  54. // 打开弹窗显示后的触发事件
  55. var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
  56. transition ?
  57. that.$dialog //找到弹窗元素
  58. .one('bsTransitionEnd', function () {
  59. // 如果支持动画,则动画结束以后给弹窗内的元素设置焦点,并触发shown事件
  60. that.$element.trigger('focus').trigger(e)
  61. })
  62. .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
  63. // 否则直接设置焦点,并触发shown事件
  64. that.$element.trigger('focus').trigger(e)
  65. })
  66. }
  67.  
  68. // 关闭弹窗
  69. Modal.prototype.hide = function (e) {
  70. //阻止冒泡
  71. if (e) e.preventDefault()
  72. //定义关闭弹窗前的触发事件
  73. e = $.Event('hide.bs.modal')
  74. //关闭弹窗前触发事件
  75. this.$element.trigger(e)
  76. // 如果已经关闭了(或者曾经被阻止过),则退出执行,后续代码不做处理
  77. if (!this.isShown || e.isDefaultPrevented()) return
  78. //设置显示状态标识为false
  79. this.isShown = false
  80. //处理键盘事件,主要是设置按Esc键的时候是否关闭弹窗
  81. this.escape()
  82. this.resize()
  83. //取消所有的focusin.bs.modal事件
  84. $(document).off('focusin.bs.modal')
  85. this.$element
  86. .removeClass('in') //删除in样式
  87. .off('click.dismiss.bs.modal') //取消dismiss的单击事件
  88. .off('mouseup.dismiss.bs.modal')//取消dismiss的鼠标抬起事件
  89. //取消dismiss的鼠标放下事件
  90. this.$dialog.off('mousedown.dismiss.bs.modal')
  91. //如果支持动画,则动画结束以后再关闭,否则直接关闭
  92. $.support.transition && this.$element.hasClass('fade') ?
  93. this.$element
  94. .one('bsTransitionEnd', $.proxy(this.hideModal, this))
  95. .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
  96. this.hideModal()
  97. }
  98.  
  99. //强制弹窗处于焦点状态
  100. Modal.prototype.enforceFocus = function () {
  101. $(document)
  102. // 禁用所有的focusin事件,防止无限循环
  103. .off('focusin.bs.modal')
  104. .on('focusin.bs.modal', $.proxy(function (e) {
  105. if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
  106. // 如果处于焦点的元素不是当前元素(或不包含当前元素),则强制给当前元素设置焦点
  107. this.$element.trigger('focus')
  108. }
  109. }, this))
  110. }
  111.  
  112. //按Esc键是否退出的处理
  113. Modal.prototype.escape = function () {
  114. if (this.isShown && this.options.keyboard) {
  115. //如果弹窗是打开状态,并且keyboard选项为true,则说明允许按ESC键可以关闭弹窗
  116. this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
  117. //检测键盘事件,如果是ESC(keycode=27),则关闭
  118. e.which == 27 && this.hide()
  119. }, this))
  120. } else if (!this.isShown) {
  121. // 否则,取消键盘事件检测
  122. this.$element.off('keydown.dismiss.bs.modal')
  123. }
  124. }
  125.  
  126. Modal.prototype.resize = function () {
  127. if (this.isShown) {
  128. $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
  129. } else {
  130. $(window).off('resize.bs.modal')
  131. }
  132. }
  133.  
  134. //关闭弹窗
  135. Modal.prototype.hideModal = function () {
  136. var that = this
  137. //关闭弹窗
  138. this.$element.hide()
  139. this.backdrop(function () {
  140. //移除body上的modal-open样式
  141. that.$body.removeClass('modal-open')
  142. that.resetAdjustments()
  143. that.resetScrollbar()
  144. //关闭以后,触发hidden事件
  145. that.$element.trigger('hidden.bs.modal')
  146. })
  147. }
  148.  
  149. //删除蒙版,关闭弹窗时触发
  150. Modal.prototype.removeBackdrop = function () {
  151. // 删除蒙版
  152. this.$backdrop && this.$backdrop.remove()
  153. // 设置蒙版对象为null
  154. this.$backdrop = null
  155. }
  156.  
  157. //添加蒙版,打开弹窗时触发
  158. Modal.prototype.backdrop = function (callback) {
  159. var that = this
  160. //是否设置了动画过渡效果,如果是则将animate设置为fade
  161. var animate = this.$element.hasClass('fade') ? 'fade' : ''
  162. //如果是打开状态,并且设置了backdrop参数
  163. if (this.isShown && this.options.backdrop) {
  164. //定义动画标识
  165. var doAnimate = $.support.transition && animate
  166. // 在body上定义蒙版div元素,并附加fade标识以支持动画
  167. this.$backdrop = $(document.createElement('div'))
  168. .addClass('modal-backdrop ' + animate)
  169. .appendTo(this.$body)
  170. //蒙版被单击时进行判断:如果backdrop参数为static,则强制将弹窗设置为售点;否则,关闭弹窗
  171. this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
  172. if (this.ignoreBackdropClick) {
  173. this.ignoreBackdropClick = false
  174. return
  175. }
  176. if (e.target !== e.currentTarget) return
  177. this.options.backdrop == 'static'
  178. ? this.$element[0].focus()
  179. : this.hide()
  180. }, this))
  181. // 如果支持动画,强制刷新UI现场,重绘弹窗
  182. if (doAnimate) this.$backdrop[0].offsetWidth
  183. //添加in样式
  184. this.$backdrop.addClass('in')
  185. //如果没有回调,则直接返回
  186. if (!callback) return
  187. // 如果支持动画,则动画结束执行回调函数;否则,直接执行回调函数
  188. doAnimate ?
  189. this.$backdrop
  190. .one('bsTransitionEnd', callback)
  191. .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
  192. callback()
  193. //如果是关闭状态,但蒙版对象依然还存在
  194. } else if (!this.isShown && this.$backdrop) {
  195. //去除in样式
  196. this.$backdrop.removeClass('in')
  197.  
  198. var callbackRemove = function () {
  199. that.removeBackdrop()
  200. callback && callback()
  201. }
  202. // 如果支持动画,则动画结束执行回调函数;否则,直接执行回调函数
  203. $.support.transition && this.$element.hasClass('fade') ?
  204. this.$backdrop
  205. .one('bsTransitionEnd', callbackRemove)
  206. .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
  207. callbackRemove()
  208.  
  209. } else if (callback) {
  210. callback()
  211. }
  212. }

【4】滚动条处理

  在弹窗插件中,使用了大量的代码对滚动条进行处理

  1. Modal.prototype.handleUpdate = function () {
  2. this.adjustDialog()
  3. }
  4.  
  5. //处理因为滚动条而使弹窗位置不固定问题
  6. Modal.prototype.adjustDialog = function () {
  7. //如果元素的高度大于页面的高度,即溢出屏幕,则modalIsOverflowing置为true
  8. var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
  9. //将元素的paddingLeft和paddingRight设置为scrollbarWidth
  10. this.$element.css({
  11. paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
  12. paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
  13. })
  14. }
  15.  
  16. //重置调节器
  17. Modal.prototype.resetAdjustments = function () {
  18. //将元素的paddingLeft和paddingRight置为空
  19. this.$element.css({
  20. paddingLeft: '',
  21. paddingRight: ''
  22. })
  23. }
  24.  
  25. //检查滚动条
  26. Modal.prototype.checkScrollbar = function () {
  27. //fullWindowWidth储存页面宽度
  28. var fullWindowWidth = window.innerWidth
  29. //IE8-浏览器不支持innerWidth属性
  30. if (!fullWindowWidth) {
  31. //使用getBoundingClientRect方法来获得页面宽度
  32. var documentElementRect = document.documentElement.getBoundingClientRect()
  33. fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left)
  34. }
  35. //如果有滚动条,则bodyIsOverflowing置为true
  36. this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth
  37. //将scrollbarWidth置为实际的滚动条宽度
  38. this.scrollbarWidth = this.measureScrollbar()
  39. }
  40.  
  41. //用来为body元素设置padding-right的值,防止body元素被scrollbar阻挡
  42. Modal.prototype.setScrollbar = function () {
  43. var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
  44. this.originalBodyPad = document.body.style.paddingRight || ''
  45. //如果页面存在滚动条,则body的padding-right设置为默认的padding-right加上滚动条的宽度
  46. if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
  47. }
  48.  
  49. //重置滚动条
  50. Modal.prototype.resetScrollbar = function () {
  51. //将body的padding-right值设置为null
  52. this.$body.css('padding-right', this.originalBodyPad)
  53. }
  54.  
  55. //测量滚动条宽度
  56. Modal.prototype.measureScrollbar = function () {
  57. var scrollDiv = document.createElement('div')
  58. scrollDiv.className = 'modal-scrollbar-measure'
  59. this.$body.append(scrollDiv)
  60. //滚动条宽度等于offetWidth - clientWidth
  61. var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
  62. this.$body[0].removeChild(scrollDiv)
  63. return scrollbarWidth
  64. }

【5】jQuery插件定义

  在jQuery上定义插件,有点特殊的代码是options参数的收集和合并,主要收集了3个部分:插件的默认参数DEFAULTS、modal元素上的data-属性,执行插件时传入的option对象,这三个部分的优先级依次升高

  1. function Plugin(option, _relatedTarget) {
  2. //根据选择器,遍历所有符合规则的元素
  3. return this.each(function () {
  4. var $this = $(this)
  5. //获取自定义属性bs.modal的值
  6. var data = $this.data('bs.modal')
  7. //将插件的默认参数DEFAULTS、modal元素上的data-属性,执行插件时传入的option对象,这三种值合并到一起,作为options参数
  8. //后面的参数的优先级高于前面的参数
  9. var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
  10. //如果值不存在,则将Modal实例设置为bs.modal值
  11. if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
  12. //如果option传递了string,则表示要执行某个方法
  13. if (typeof option == 'string') data[option](_relatedTarget)
  14. else if (options.show) data.show(_relatedTarget)
  15. })
  16. }
  17.  
  18. var old = $.fn.modal
  19. //保留其他库的$.fn.modal代码(如果定义的话),以便在noConflict之后可以继续使用该老代码
  20. $.fn.modal = Plugin
  21. //重设插件构造器,可以通过该属性获取插件的真实类函数
  22. $.fn.modal.Constructor = Modal

【6】防冲突处理

  1. $.fn.modal.noConflict = function () {
  2. //恢复以前的旧代码
  3. $.fn.modal = old
  4. //将$.fn.modal.noConflict()设置为Bootstrap的Modal插件
  5. return this
  6. }

【7】绑定触发事件

  1. //监测所有拥有自定义属性data-toggle="modal"的元素上的单击事件
  2. $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
  3. var $this = $(this)
  4. //获取href属性值
  5. var href = $this.attr('href')
  6. //获取data-target属性值,如果没有,则获取href值,该值是所弹出元素的id
  7. var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, '')))
  8. //如果弹窗元素上已经弹窗实例(即弹出过一次了),则设置option值为字符串toggle,否则将remote值(如果有的话)、弹窗元素上的自定义属性值集合、触发元素上的自定义属性值集合,合并为option对象
  9. var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
  10. //如果是a链接,则阻止其默认行为
  11. if ($this.is('a')) e.preventDefault()
  12. $target.one('show.bs.modal', function (showEvent) {
  13. if (showEvent.isDefaultPrevented()) return
  14. //定义一次hidden事件,给所单击元素设置focus
  15. $target.one('hidden.bs.modal', function () {
  16. $this.is(':visible') && $this.trigger('focus')
  17. })
  18. })
  19. Plugin.call($target, option, this)
  20. })
  21.  
  22. }(jQuery);

Bootstrap模态弹出框的更多相关文章

  1. 玩转Bootstrap(JS插件篇)-第1章 模态弹出框 :1-4 模态弹出框--结构分析

    模态弹出框--结构分析 Bootstrap框架中的模态弹出框,分别运用了“modal”.“modal-dialog”和“modal-content”样式,而弹出窗真正的内容都放置在“modal-con ...

  2. 玩转Bootstrap(JS插件篇)-第1章 模态弹出框 :1-3 模态弹出框

    模态弹出框(Modals) 这一小节我们先来讲解一个“模态弹出框”,插件的源文件:modal.js. 右侧代码编辑器(30行)就是单独引入 bootstrap 中发布出的“modal.js”文件. 样 ...

  3. bootstrap中的modal 模态弹出框不能放在 form_for里面,一弹出modal会自动submit掉form

    bootstrap中的modal 模态弹出框不能放在 form_for里面,一弹出modal会自动submit掉form

  4. Bootstrap模态弹出窗

    Bootstrap模态弹出窗有三种方式: 1.href触发模态弹出窗元素: <a class="btn btn-primary" data-toggle="moda ...

  5. Bootstrap:弹出框和提示框效果以及代码展示

    前言:对于Web开发人员,弹出框和提示框的使用肯定不会陌生,比如常见的表格新增和编辑功能,一般常见的主要有两种处理方式:行内编辑和弹出框编辑.在增加用户体验方面,弹出框和提示框起着重要的作用,如果你的 ...

  6. JS组件Bootstrap实现弹出框和提示框效果代码

    这篇文章主要介绍了JS组件Bootstrap实现弹出框和提示框效果代码,对弹出框和提示框感兴趣的小伙伴们可以参考一下 前言:对于Web开发人员,弹出框和提示框的使用肯定不会陌生,比如常见的表格新增和编 ...

  7. UIPresentationController - iOS自定义模态弹出框

    参考: https://developer.apple.com/library/archive/featuredarticles/ViewControllerPGforiPhoneOS/Definin ...

  8. Bootboxjs快速制作Bootstrap的弹出框效果

    Bootboxjs是一个简单的js库,简单快捷帮你制作一个Bootstrap的弹出框效果. 一.简介 bootbox.js是一个小的JavaScript库,它帮助您在使用bootstrap框架的时候快 ...

  9. [Bootstrap]modal弹出框

    写在前面 在实际开发中,为了友好,更需要一种美观的弹出框,js原生的alert,很难满足需求.这里推荐一个bootstrap的弹出框. 一个例子 先看效果吧 代码: <!DOCTYPE html ...

随机推荐

  1. Javascript性能优化之节流函数

    在我们的工作中往往有这样的需求,下拉上拉加载实现无限加载列表数据这样的一个功能,这个时候小伙伴们可能就觉得这个功能几分钟的事,于是乎,下边这段代码浩浩荡荡就出来了 window.addEventLis ...

  2. linux中搭建java开发环境

    JDK安装 http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 下载对应jdk版本, ...

  3. windows下Python 3.x图形图像处理库PIL的安装

    图像处理是一门应用非常广的技术,而拥有非常丰富第三方扩展库的 Python 当然不会错过这一门盛宴.PIL (Python Imaging Library)是 Python 中最常用的图像处理库,目前 ...

  4. GoodReads: Machine Learning (Part 3)

    In the first installment of this series, we scraped reviews from Goodreads. In thesecond one, we per ...

  5. Java之JSON数据

    特别注意:使用JSON前需要导包 操作步骤地址:http://blog.csdn.net/baidu_37107022/article/details/70876993 1.定义 JSON(JavaS ...

  6. 高CPU、数据库无法读写的真凶

    有兴趣的同学可以参考如下系列文章,都是针对dump分析的实战和总结: Windbg DUMP分析(原创汇总) http://www.cnblogs.com/LoveOfPrince/p/6653341 ...

  7. Android 图片加载框架Glide4.0源码完全解析(一)

    写在之前 上一篇博文写的是Picasso基本使用和源码完全解析,Picasso的源码阅读起来还是很顺畅的,然后就想到Glide框架,网上大家也都推荐使用这个框架用来加载图片,正好我目前的写作目标也是分 ...

  8. vue init webpack-simple project 报错处理(connect ETIMEDOUT 192.30.253.112)

    Failed to download repo vuejs-templates/webpack-simple: connect ETIMEDOUT 192.30.253.113:443 Failed ...

  9. CSS中的尺寸单位

    绝对单位 px: Pixel 像素 pt: Points 磅 pc: Picas 派卡 in: Inches 英寸 mm: Millimeter 毫米 cm: Centimeter 厘米 q: Qua ...

  10. 原生js实现Ajax的原理。

    Ajax(Asynchronous JavaScript and XML)表示异步的js与xml. 有别于传统web的同步开发方式. 原理:通过XMLHttpRequest对象向服务器发送异步请求,从 ...