/* ========================================================================
* Bootstrap: modal.js v3.3.5
* http://getbootstrap.com/javascript/#modals
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */ +function ($) {
'use strict'; // MODAL CLASS DEFINITION
// ====================== var Modal = function (element, options) {// element表示modal弹出框容器及内部元
//素,options是设置选项
this.options = options
this.$body = $(document.body)
this.$element = $(element)
this.$dialog = this.$element.find('.modal-dialog')
this.$backdrop = null
this.isShown = null
this.originalBodyPad = null
this.scrollbarWidth = 0
this.ignoreBackdropClick = false // 如果设置了remote,就加载remote指定url的内容到modal-content样式的元素内,并触发
// loaded.bs.modal事件
if (this.options.remote) {
this.$element
.find('.modal-content')
.load(this.options.remote, $.proxy(function () {
this.$element.trigger('loaded.bs.modal')
}, this))
}
} Modal.VERSION = '3.3.5' Modal.TRANSITION_DURATION = 300
Modal.BACKDROP_TRANSITION_DURATION = 150 Modal.DEFAULTS = {
backdrop: true,// 默认单击弹窗以外的地方时自动关闭弹窗
keyboard: true,// 默认设置,按Esc键关闭弹窗
show: true// 默认设置,单击触发元素时打开弹窗
}
// 反转弹窗状态
Modal.prototype.toggle = function (_relatedTarget) {
return this.isShown ? this.hide() : this.show(_relatedTarget)
}
// 打开弹窗
Modal.prototype.show = function (_relatedTarget) {
var that = this
var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
// 打开弹窗前,触发事件
this.$element.trigger(e)
// 如果已经打开了(或者曾经被阻止过),则退出执行,后续代码不做处理
if (this.isShown || e.isDefaultPrevented()) return this.isShown = true this.checkScrollbar()
this.setScrollbar()
this.$body.addClass('modal-open') this.escape()
this.resize()
// 如果单击了元素内的子元素(带有[data-dismiss="modal"]属性),则关闭弹窗
this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this)) this.$dialog.on('mousedown.dismiss.bs.modal', function () {
that.$element.one('mouseup.dismiss.bs.modal', function (e) {
if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true
})
}) this.backdrop(function () {
// 判断浏览器是否支持动画,并且弹窗是否设置了动画过渡效果(是否有fade样式)
var transition = $.support.transition && that.$element.hasClass('fade')
// 如果modal弹窗没有父容器,则将它附加到body上
if (!that.$element.parent().length) {
that.$element.appendTo(that.$body) // don't move modals dom position
}
// 显示modal弹窗
that.$element
.show()
.scrollTop(0) that.adjustDialog()
// 如果支持动画,强制刷新UI现场,重绘弹窗
if (transition) {
that.$element[0].offsetWidth // force reflow
}
// 给modal弹窗添加in样式,和modal样式一起
that.$element.addClass('in')
// 强制给弹窗设定焦点
that.enforceFocus()
// 打开弹窗显示后的触发事件
var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) transition ?
that.$dialog // wait for modal to slide in
.one('bsTransitionEnd', function () {// 如果支持动画,则动画结束以后给弹窗内的元素设置焦点,并触发shown事件
that.$element.trigger('focus').trigger(e)
})// 否则直接设置焦点,并触发shown事
.emulateTransitionEnd(Modal.TRANSITION_DURATION) :
that.$element.trigger('focus').trigger(e)
})
}
// 关闭弹窗
Modal.prototype.hide = function (e) {
if (e) e.preventDefault()// 先阻止冒泡行为
// 关闭弹窗前的触发事件
e = $.Event('hide.bs.modal') this.$element.trigger(e) if (!this.isShown || e.isDefaultPrevented()) return this.isShown = false
// 处理键盘事件,主要是设置按Esc键的时候是否
//关闭弹窗
this.escape()
this.resize() $(document).off('focusin.bs.modal') this.$element
.removeClass('in')
.off('click.dismiss.bs.modal')
.off('mouseup.dismiss.bs.modal') this.$dialog.off('mousedown.dismiss.bs.modal')
// 如果支持动画,则动画结束以后再关闭,否则直接关闭
$.support.transition && this.$element.hasClass('fade') ?
this.$element
.one('bsTransitionEnd', $.proxy(this.hideModal, this))
.emulateTransitionEnd(Modal.TRANSITION_DURATION) :
this.hideModal()
}
// 确保当前打开的弹窗处于焦点状态
Modal.prototype.enforceFocus = function () {
$(document)// 禁用所有的focusin事件,防止无限循环
.off('focusin.bs.modal') // guard against infinite focus loop
.on('focusin.bs.modal', $.proxy(function (e) {
if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
this.$element.trigger('focus')
}// 如果处于焦点的元素不是当前元素(或不包含当前元素),则强制给当前元素设置
//焦点
}, this))
}
// 按Esc键是否退出的处理
Modal.prototype.escape = function () {
if (this.isShown && this.options.keyboard) {
this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
e.which == 27 && this.hide()
}, this))
} else if (!this.isShown) {// 否则,取消键盘事件检测
this.$element.off('keydown.dismiss.bs.modal')
}
} Modal.prototype.resize = function () {
if (this.isShown) {
$(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
} else {
$(window).off('resize.bs.modal')
}
}
// 关闭弹窗
Modal.prototype.hideModal = function () {
var that = this
this.$element.hide()
this.backdrop(function () {
that.$body.removeClass('modal-open')
that.resetAdjustments()
that.resetScrollbar()
that.$element.trigger('hidden.bs.modal')
})
}
// 删除背景,关闭弹窗时触发
Modal.prototype.removeBackdrop = function () {
this.$backdrop && this.$backdrop.remove()// 删除背景元素
this.$backdrop = null// 设置背景对象为null
}
// 添加背景,打开弹窗时触发
Modal.prototype.backdrop = function (callback) {
var that = this
// 是否设置了动画过渡效果,如果是则
//设置为fade
var animate = this.$element.hasClass('fade') ? 'fade' : ''
// 如果是打开状态,并且设置了backdrop参数
if (this.isShown && this.options.backdrop) {
var doAnimate = $.support.transition && animate // 在body上定义背景div元素,并附加fade标识以支持动画
this.$backdrop = $(document.createElement('div'))
.addClass('modal-backdrop ' + animate)
.appendTo(this.$body) this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
if (this.ignoreBackdropClick) {
this.ignoreBackdropClick = false
return
}
if (e.target !== e.currentTarget) return
this.options.backdrop == 'static'
? this.$element[0].focus()
: this.hide()
}, this)) if (doAnimate) this.$backdrop[0].offsetWidth // force reflow this.$backdrop.addClass('in') if (!callback) return doAnimate ?
this.$backdrop
.one('bsTransitionEnd', callback)
.emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
callback() } else if (!this.isShown && this.$backdrop) {
this.$backdrop.removeClass('in') var callbackRemove = function () {
that.removeBackdrop()
callback && callback()
}
$.support.transition && this.$element.hasClass('fade') ?
this.$backdrop
.one('bsTransitionEnd', callbackRemove)
.emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
callbackRemove() } else if (callback) {
callback()
}
} // these following methods are used to handle overflowing modals Modal.prototype.handleUpdate = function () {
this.adjustDialog()
} Modal.prototype.adjustDialog = function () {
var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight this.$element.css({
paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
})
} Modal.prototype.resetAdjustments = function () {
this.$element.css({
paddingLeft: '',
paddingRight: ''
})
} Modal.prototype.checkScrollbar = function () {
var fullWindowWidth = window.innerWidth
if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
var documentElementRect = document.documentElement.getBoundingClientRect()
fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left)
}
this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth
this.scrollbarWidth = this.measureScrollbar()
} Modal.prototype.setScrollbar = function () {
var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
this.originalBodyPad = document.body.style.paddingRight || ''
if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
} Modal.prototype.resetScrollbar = function () {
this.$body.css('padding-right', this.originalBodyPad)
} Modal.prototype.measureScrollbar = function () { // thx walsh
var scrollDiv = document.createElement('div')
scrollDiv.className = 'modal-scrollbar-measure'
this.$body.append(scrollDiv)
var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
this.$body[0].removeChild(scrollDiv)
return scrollbarWidth
} // MODAL PLUGIN DEFINITION
// ======================= function Plugin(option, _relatedTarget) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.modal')
var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option) if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
if (typeof option == 'string') data[option](_relatedTarget)
else if (options.show) data.show(_relatedTarget)
})
} var old = $.fn.modal $.fn.modal = Plugin
$.fn.modal.Constructor = Modal // MODAL NO CONFLICT
// ================= $.fn.modal.noConflict = function () {
$.fn.modal = old
return this
} // MODAL DATA-API
// ============== $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
var $this = $(this)
var href = $this.attr('href')
var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data()) if ($this.is('a')) e.preventDefault() $target.one('show.bs.modal', function (showEvent) {
if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
$target.one('hidden.bs.modal', function () {
$this.is(':visible') && $this.trigger('focus')
})
})
Plugin.call($target, option, this)
}) }(jQuery);

Bootstrap modal.js 源码分析的更多相关文章

  1. basket.js 源码分析

    basket.js 源码分析 一.前言 basket.js 可以用来加载js脚本并且保存到 LocalStorage 上,使我们可以更加精准地控制缓存,即使是在 http 缓存过期之后也可以使用.因此 ...

  2. events.js 源码分析

    events.js 源码分析 1. 初始化 // 使用 this.ee = new EventEmitter(); // 源码 // 绑定this域,初始化 _events,_eventsCount和 ...

  3. Bootstrap 模态窗口源码分析

    前言: bootstrap的 js插件的源码写的非常好,也算是编写jquery插件的模范写法,本来还想大篇详细的分析一下呢,唉,没时间啊,很早之前看过的源码了,现在贴在了博客上, 300来行的代码,其 ...

  4. Backbone.js源码分析(珍藏版)

    源码分析珍藏,方便下次阅读! // Backbone.js 0.9.2 // (c) 2010-2012 Jeremy Ashkenas, DocumentCloud Inc. // Backbone ...

  5. Require.js 源码分析

    本文将简单介绍下个人对require.js的源码分析,简单分析实现原理 一.require加载资源的流程 require中,根据AMD(Asynchronous Module Definition)的 ...

  6. Vue.js 源码分析(三十一) 高级应用 keep-alive 组件 详解

    当使用is特性切换不同的组件时,每次都会重新生成组件Vue实例并生成对应的VNode进行渲染,这样是比较花费性能的,而且切换重新显示时数据又会初始化,例如: <!DOCTYPE html> ...

  7. Vue.js 源码分析(三十) 高级应用 函数式组件 详解

    函数式组件比较特殊,也非常的灵活,它可以根据传入该组件的内容动态的渲染成任意想要的节点,在一些比较复杂的高级组件里用到,比如Vue-router里的<router-view>组件就是一个函 ...

  8. Vue.js 源码分析(二十九) 高级应用 transition-group组件 详解

    对于过度动画如果要同时渲染整个列表时,可以使用transition-group组件. transition-group组件的props和transition组件类似,不同点是transition-gr ...

  9. Vue.js 源码分析(二十八) 高级应用 transition组件 详解

    transition组件可以给任何元素和组件添加进入/离开过渡,但只能给单个组件实行过渡效果(多个元素可以用transition-group组件,下一节再讲),调用该内置组件时,可以传入如下特性: n ...

随机推荐

  1. php利用msqli访问数据库并实现分页,

    <?php require_once 'login.php'; $num_rec_per_page=2; // 每页显示数量 //mysql_connect('localhost','jim', ...

  2. bzoj1797: [Ahoi2009]Mincut 最小割(最小割+强联通tarjan)

    1797: [Ahoi2009]Mincut 最小割 题目:传送门 题解: 感觉是一道肥肠好的题目. 第二问其实比第一问简单? 用残余网络跑强联通,流量大于0才访问. 那么如果两个点所属的联通分量分别 ...

  3. m_Orchestrate learning system---十九、局部变量和块变量是什么

    m_Orchestrate learning system---十九.局部变量和块变量是什么 一.总结 一句话总结:下面的global的使用情况可以很好的解释这个问题 这是在一个函数里面,只不过里面有 ...

  4. [jzoj 5178] [NOIP2017提高组模拟6.28] So many prefix? 解题报告(KMP+DP)

    题目链接: https://jzoj.net/senior/#main/show/5178 题目: 题解: 我们定义$f[pos]$表示以位置pos为后缀的字符串对答案的贡献,答案就是$\sum_{i ...

  5. CAS算法

    /** * CAS(Compare-And-Swap)算法保证了数据的原子性 * CAS算法是硬件对于并发操作共享数据的支持 * CAS包含了3个操作数: * 内存值 V 看成两步 读取内存值为1步 ...

  6. Redis常用命令速查 <第二篇>【转】

    一.Key Key命令速查: 命令 说明 DEL 删除给定的一个或多个 key,不存在的 key 会被忽略,返回值:被删除 key 的数量 DUMP 序列化给定 key,返回被序列化的值,使用 RES ...

  7. C#语言基础之第一个C#程序

    1.在记事本中编写如下代码,保存为Simple.cs文件. using System; class Hello World{ public static void Main(){ Console.Wr ...

  8. ZOJ 3321 Circle【并查集】

    解题思路:给定n个点,m条边,判断是否构成一个环 注意到构成一个环,所有点的度数为2,即一个点只有两条边与之相连,再有就是判断合并之后这n个点是否在同一个连通块 Circle Time Limit: ...

  9. 贰、js的基础(二)类型转换

    JS 数据类型转换 方法主要有三种 转换函数.强制类型转换.利用js变量弱类型转换. 1. 转换函数: js提供了parseInt()和parseFloat()两个转换函数.前者把值转换成整数,后者把 ...

  10. 【BZOJ4176】Lucas的数论-杜教筛

    求$$\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}f(ij)$$,其中$f(x)$表示$x$的约数个数,$0\leq n\leq 10^9$,答案膜$10^9+ ...