bootstrap插件学习-bootstrap.modal.js

先从bootstrap.modal.js的结构看起。

function($){
var Modal = function(){} //构造器
Modal.prototype = function(){} //构造器的原型
function ..(){} //自定义方法
$.fn.modal = function(){} //在jQuery对象上自定方法
$.fn.modal.defaults = {} //设置默认属性
$.fn.modal.Constructor = Modal //重置构造器名
$(function(){}) //初始化
}(window.jQuery)

其HTML结构

<a class="btn" data-toggle="modal" href="#myModal" >点击触发对话框</a>

<div class="modal" id="myModal">
<div class="modal-header">
<a class="close" data-dismiss="modal">×</a>
<h3>对话框标题</h3>
</div>
<div class="modal-body">
<p>对话框内容</p>
</div>
<div class="modal-footer">
<a href="#" class="btn" data-dismiss="modal">关闭</a>
<a href="#" class="btn btn-primary" data-dismiss="modal">保存更新</a>
</div>
</div>

我们开始过一遍插件源码:从初始化开始

$(function () {
/*
* 在所有有data-toggle='modal'属性的标签上帮上click事件,一般为a标签
* /.*(?=#[^\s]+$)/表示如果匹配成功将#之前的信息删除
* 对于jQuery对象,比如a标签有data-xx类型的,在其data方法中都可以显示
* 将a标签data-target指向的或是href的锚点指向的元素传入modal方法里
* */
$('body').on('click.modal.data-api', '[data-toggle="modal"]', function ( e ) {
var $this = $(this), href
, $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
, option = $target.data('modal') ? 'toggle' : $.extend({}, $target.data(), $this.data());
e.preventDefault()
$target.modal(option)
})
})

根据HTML提供的结构,$target为a标签所指向的弹出框div的Jquery对象。另外$this.data()存在数据,为{toggle:'modal'},这个我在注释中已经解释。最后执行$target.modal(option),我们进入jQuery对象的这个方法。

$.fn.modal = function ( option ) {
return this.each(function () {
var $this = $(this)
, data = $this.data('modal')
, options = $.extend({}, $.fn.modal.defaults, $this.data(), typeof option == 'object' && option)
if (!data) $this.data('modal', (data = new Modal(this, options)))//为modal绑定对象
if (typeof option == 'string') data[option]()
else if (options.show) data.show()
})
}

初始化一些参数,在弹出框div上加入了一个modal属性,如果这个modal属性不存在,则实例化Modal构造器。最后执行show方法,因为此时你已经点击了a标签,让div显示。代码中有if(typeof option == 'string')data[option],表示代码支持传入方法名,执行该方法,在执行show方法之前,我们先进入Modal的构造器中看看。

/*
* 构造器,为所有data-dismiss='modal'属性的标签绑定原型上的hide方法
* */
var Modal = function ( content, options ) {
this.options = options
this.$element = $(content)
.delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this))
}

很简单,让带有data-dismiss='modal'属性的标签的click事件交给弹出框div代理,注意这里的执行的方法。这里为什么要$.proxy(this.hide,this)这样写,第一,需要明白此时的this表示着构造器的实例,代理的事件需要使用到实例的hide方法,为什么实例拥有hide方法,很简单this是Modal的实例,它继承了Modal原型的方法。那proxy方法中的第二个this,则表示着这个hide方法的调用者,即上下文,可以试想一下,如果我们不修改这个,那执行这个方法时,其里面的this是不是指向了调用它的a标签呢?(注意留意HTML结构,拥有data-dismiss属性的三个a标签,其实分别就是弹出框的关闭按钮等),那原来定义在原型上的hide方法中的this的属性将不能在正常使用。
综上,实例化,主要就是给弹出框绑定了hide事件,为将来关闭弹出框,做准备。

好,回到之前JQuery的modal方法上,最后我们执行了show方法,进入show方法。

下面是执行的流程图,就是各个方法的执行顺序

show -> escape -> backdrop
hide ->escape -> hideModal -> backdrop

show

    , show: function () {
var that = this if (this.isShown) return $('body').addClass('modal-open')//给body加上modal-open类 this.isShown = true//将isShown属性设置成true this.$element.trigger('show');//没理解
escape.call(this)//加上键盘事件 backdrop.call(this, function () {
var transition = $.support.transition && that.$element.hasClass('fade') //console.log(that.$element);
/*
* 插入弹出层
* */
!that.$element.parent().length && that.$element.appendTo(document.body) //don't move modals dom position that.$element
.show()//jQuery方法显示 if (transition) {
that.$element[0].offsetWidth // force reflow
} that.$element.addClass('in') transition ?
that.$element.one($.support.transition.end, function () { that.$element.trigger('shown') }) :
that.$element.trigger('shown') })
}

谈到show和hide的时候,我们需要留意它们源码中的一些我们认为的'废'操作,其实它能帮助我们实现扩展。比如给body加modal-open这个类,如果你要在打开弹出层,执行其他程序,可以通过判断这个类来实现,这是bootstrap它自身已经提供的标识。escape()方法是一个添加键盘事件和删除键盘事件的方法,它可以让你按enter键也能关闭弹出框,比较简单。

接下来我们进入backdrop方法

/*
* 生成遮罩层,并且控制遮罩层的显示或删除
* */
function backdrop( callback ) {
var that = this
, animate = this.$element.hasClass('fade') ? 'fade' : '' if (this.isShown && this.options.backdrop) {
var doAnimate = $.support.transition && animate
//console.log(doAnimate);
this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
.appendTo(document.body)//遮罩层,让弹出框显示时,背景被遮罩,此时为透明的 if (this.options.backdrop != 'static') {
this.$backdrop.click($.proxy(this.hide, this))
} if (doAnimate) this.$backdrop[0].offsetWidth // force reflow this.$backdrop.addClass('in')//加入in类,显示遮罩层 doAnimate ?
this.$backdrop.one($.support.transition.end, callback) :
callback()
//打开时,执行callback()回调
} else if (!this.isShown && this.$backdrop) {
this.$backdrop.removeClass('in')//删除in,遮罩层透明
$.support.transition && this.$element.hasClass('fade')?
this.$backdrop.one($.support.transition.end, $.proxy(removeBackdrop, this)) :
removeBackdrop.call(this)
//一般执行removeBackdrop()函数
} else if (callback) {
callback()
}
}

这里为什么要判断弹出框是否有fade类,在bootstrap.css中,.fade拥有left:-25%的属性,当.fade .in时则left变为10%,在版本较高的浏览器中,有自上向下的移动的效果(低版本浏览器没有效果,不过这个可以jQuery实现...),这个部分需要我们结合css样式看,注意in的样式,就可以了,弹出框显示的最后一步,执行callback回调,显示弹出框,并给弹出框加上in类,80%透明度。最后完成显示。

之前因为我们已经在弹出框的三个a标签上都绑定了hide事件,所以当我们点击关闭时,执行hide方法

hide: function ( e ) {
e && e.preventDefault() if (!this.isShown) return var that = this
this.isShown = false $('body').removeClass('modal-open') escape.call(this)//关闭按键事件 this.$element
.trigger('hide')
.removeClass('in')//jQuery方法,将弹出框隐藏,并将div的class去in $.support.transition && this.$element.hasClass('fade') ?
hideWithTransition.call(this) :
hideModal.call(this)
}

其实跟show方法差不多,主要是给show擦屁股,进入hideModal方法

function hideModal( that ) {
this.$element
.hide() //删除效果更好
.trigger('hidden') backdrop.call(this)
}

蛮蛋疼的方法,还是调用backdrop。最后删除时我们调用的是removeBackdrop方法。

/*
* 清除遮罩层
* */
function removeBackdrop() {
this.$backdrop.remove()
this.$backdrop = null
}

将之前创建的遮罩层删除。以上完成一遍弹出框的打开显示。

内容不多,时间刚好,以上是我的一点读码体会,如有错误,请指出,大家共通学习。

bootstrap插件学习-bootstrap.modal.js的更多相关文章

  1. bootstrap插件学习-bootstrap.dropdown.js

    bootstrap插件学习-bootstrap.dropdown.js 先看bootstrap.dropdown.js的结构 var toggle = '[data-toggle="drop ...

  2. bootstrap插件学习-bootstrap.carousel.js

    先看bootstrap.carousel.js的结构 var Carousel = function (element, options){} //构造器 Carousel.prototype = { ...

  3. bootstrap插件学习-bootstrap.scrollspy.js

    先看bootstrap.dropdown.js的结构 function ScrollSpy(){} //构造函数 ScrollSpy.prototype = {} //构造器的原型 $.fn.scro ...

  4. bootstrap插件学习-bootstrap.typehead.js

    先看bootstrap.typehead.js的结构 var Typeahead = function ( element, options ){} //构造器 Typeahead.prototype ...

  5. bootstrap插件学习-bootstrap.collapse.js

    先看bootstrap.collapse.js的结构 var Collapse = function ( element, options ){} // 构造器 Collapse.prototype ...

  6. bootstrap插件学习-bootstrap.alert.js

    我们先看bootstrap.alert.js的结构 var dismiss = '[data-dismiss="alert"]' //自定义属性 Alert = function ...

  7. bootstrap插件学习-bootstrap.button.js

    先看bootstrap.button.js的结构 var Button = function ( element, options ){} //构造器 Button.prototype = {} // ...

  8. bootstrap插件学习-bootstrap.popover.js

    先看bootstrap.popover.js的结构 var Popover = function ( element, options ){} //构造器 Popover.prototype = {} ...

  9. bootstrap插件学习-bootstrap.tooltip.js

    先看bootstrap-tooltip.js的结构 var Tooltip = function ( element, options ){} // 构造器 Tooltip.prototype ={} ...

随机推荐

  1. Tair LDB基于Prefixkey找到如何提取一系列性能优化项目key的prefix_size

    眼下项目已快截止,编码任务也基本完毕.如今主要是性能測试. 项目是依照"Tair LDB基于Prefixkey的范围查找性能优化项目提议方案"的步骤一步步完毕的,首先先介绍第一个关 ...

  2. 从头学起android&lt;AutoCompleteTextView文章提示文本框.十九.&gt;

    文章提示可以很好的帮助用户输入信息,以方便.在Android它也设置有类似特征,而要实现这个功能需要依靠android.widget.AutoCompleteTextView完毕,此类的继承结构例如以 ...

  3. session什么时候被创建

    一个常见的错误是以为 session 在有客户端访问时就被创建,然而事实是直到某 server 端程序(如 Servlet )调用HttpServletRequest.getSession(true) ...

  4. [Unity3D]Unity3D连衣裙实现游戏开发系统

    大家好,我是秦培.欢迎关注我的博客,我的博客地址">blog.csdn.net/qinyuanpei. 不知从什么时候開始,国产RPG单机游戏開始出现换装,仙剑系列中第一部实现了换装的 ...

  5. vs.net 2013 Saffolding功能扩展

    vs.net 2013 Saffolding功能扩展 Asp.net mvc 5 CRUD代码自动生成工具 -Visual Studio.net2013 Saffolding功能扩展 上次做过一个&l ...

  6. Java利用jcifs集成AD域用户认证

    近期一段时间发现AD这东西老火了,尤其是涉及到安全这一方面的,所以AD域用户认证成了如今网络安全方面的产品必备!这里就简单的分享一下,Java通过jcifs集成AD域用户实现认证,以实现网络安全! 我 ...

  7. MySQL引擎介绍ISAM,MyISAM,HEAP,InnoDB

    MySQL数据库引擎取决于MySQL在安装的时候是如何被编译的.要添加一个新的引擎,就必须重新编译MYSQL. 在缺省情况下,MYSQL支持三个引擎:ISAM.MYISAM和HEAP.另外两种类型IN ...

  8. [Elasticsearch] 集群工作 - 第二部分

    本文翻译自Elasticsearch官方指南的life inside a cluster一章. 添加故障转移(Failover)功能 仅仅执行一个节点意味着可能存在着单点失败(Single point ...

  9. HDU 2079-课程时间(生成函数)

    课程时间(标题已被修改,注意阅读题) Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  10. Android多媒体-MediaRecorder 录制音视频

    不多说,直接上代码,有具体凝视 MyAudioRecord.java import java.io.File; import java.io.IOException; import android.a ...