博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Bootstrap的Model源码详细注释 (转)
阅读量:6974 次
发布时间:2019-06-27

本文共 11821 字,大约阅读时间需要 39 分钟。

 

原文: http://my.oschina.net/haogrgr/blog/323079?p=1

/* ======================================================================== * Bootstrap: modal.js v3.2.0 * http://getbootstrap.com/javascript/#modals * ======================================================================== * Copyright 2011-2014 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ //这里的 +function($){}(jQuery) 和 (function($){})(jQuery) 一个意思+function($) {    'use strict';     // MODAL CLASS DEFINITION    // ======================     var Modal = function(element, options) {        this.options = options        this.$body = $(document.body)        this.$element = $(element)        this.$backdrop = this.isShown = null        this.scrollbarWidth = 0         // 如果是远程内容,就加载,并触发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.2.0'         // 默认配置    Modal.DEFAULTS = {        backdrop : true, // 默认配置,要背景div(单击触发hide方法)        keyboard : true, // 要desc键按了就消失的功能        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)// 触发show.bs.modal事件         // 如果已经显示了, 或者上面事件回调中调用了e.preventDefault 就 直接不处理,直接返回        if (this.isShown || e.isDefaultPrevented()) return                 //改变显示状态为显示中        this.isShown = true             //有滚动条的话,就设置滚动条的宽度        this.checkScrollbar()        //overflow:hidden        this.$body.addClass('modal-open')        //padding-right 属性在原来的基础上 + 上面算出来的滚动条的宽度        this.setScrollbar()                 //如果options.keyboard配置为true则监听keyup.dismiss.bs.modal事件, 功能就是按esc键,就调用hide方法        this.escape()             //为包含data-dismiss="modal"属性的元素注册关闭处理器(比如点x按钮,就隐藏模态框功能)        this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))             //backdrop函数:背景逻辑, 回调函数功能:显示model逻辑        this.backdrop(function () {            // 浏览器是否支持动画 & model的元素包含fade class            var transition = $.support.transition && that.$element.hasClass('fade')             // 没有父元素(例:还未append的$("
")),则将model附加到body上, if (!that.$element.parent().length) { that.$element.appendTo(that.$body) // don't move modals dom position } // 将model元素设置成显示(jq.show方法), 并移动到最上面 that.$element.show().scrollTop(0) //动画效果准备 if (transition) { that.$element[0].offsetWidth // force reflow } //设置不透明opacity:1, 设置显示(aria,给不方便人士用的)aria-hidden:false that.$element.addClass('in').attr('aria-hidden', false); //解绑并为document对象注册focusin.bs.modal事件, 具体处理是:如果不是model产生的,就触发model的facus事件 //简单的说,就是聚焦,哈哈,看着我,看着我 that.enforceFocus() //准备触发shown.bs.modal事件 var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) //有动画,就动画完成后触发focus事件和shown.bs.modal事件 transition ? that.$element.find('.modal-dialog') // wait for modal to slide in .one('bsTransitionEnd', function () { that.$element.trigger('focus').trigger(e) }) .emulateTransitionEnd(300) : that.$element.trigger('focus').trigger(e) }) } //隐藏model方法 Modal.prototype.hide = function(e) { if (e) e.preventDefault() //不清楚作用场景 //准备触发隐藏事件, 并触发 e = $.Event('hide.bs.modal') this.$element.trigger(e) //如果model状态以及为未显示 或者上面事件回调函数中调用了preventDefault, 就不处理 if (!this.isShown || e.isDefaultPrevented()) return //设置状态为不显示 this.isShown = false //去掉显示时加上的class, 具体就是overflow:hidden this.$body.removeClass('modal-open') //还原padding-right属性 设置为'' (对应show中的setScrollbar) this.resetScrollbar() ////解除keyup.dismiss.bs.modal, 与show方法里的对应 this.escape() //解除document对象的focusin.bs.modal事件绑定, (对应show中enforceFocus) $(document).off('focusin.bs.modal') //移除不透明设置(in), 设置为隐藏, 移除关闭处理器(比如点x按钮,就隐藏模态框功能) this.$element.removeClass('in').attr('aria-hidden', true).off('click.dismiss.bs.modal') //动画,然后调用hideModal方法(加上背景div的关联处理) $.support.transition && this.$element.hasClass('fade') ? this.$element .one('bsTransitionEnd', $.proxy(this.hideModal, this)) .emulateTransitionEnd(300) : this.hideModal() } //解绑并为document对象注册focusin.bs.modal事件, 具体处理是:如果不是model产生的,就触发model的facus事件 Modal.prototype.enforceFocus = function () { $(document).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键时,隐藏model功能,(根据配置) Modal.prototype.escape = function () { if (this.isShown && this.options.keyboard) { this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) { e.which == 27 && this.hide() }, this)) } else if (!this.isShown) { this.$element.off('keyup.dismiss.bs.modal') } } //隐藏关联方法,隐藏元素,并处理背景div,并触发隐藏完成事件 Modal.prototype.hideModal = function () { var that = this //隐藏model自身(jq.hide) this.$element.hide() //隐藏背景逻辑 this.backdrop(function () { //触发隐藏完成事件 that.$element.trigger('hidden.bs.modal') }) } //移除背景div Modal.prototype.removeBackdrop = function () { this.$backdrop && this.$backdrop.remove() this.$backdrop = null } //callback为具体的model的隐藏或显示逻辑,backdrop负责背景div逻辑 Modal.prototype.backdrop = function (callback) { var that = this //是否包含fade样式(动画) var animate = this.$element.hasClass('fade') ? 'fade' : '' //如果为显示中 且 要背景div if (this.isShown && this.options.backdrop) { var doAnimate = $.support.transition && animate //添加背景div this.$backdrop = $('
').appendTo(this.$body) //绑定click.dismiss.bs.modal事件, this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) { //冒泡来的事件不管,不过一般model都在最外面,so,这里一般不会返回false; if (e.target !== e.currentTarget) return //如果backdrop配置参数为static, 则获取焦点,否则,调用隐藏方法 this.options.backdrop == 'static' ? this.$element[0].focus.call(this.$element[0]) : this.hide.call(this) }, this)) //准备动画 if (doAnimate) this.$backdrop[0].offsetWidth // force reflow //设置背景div半透明opacity:0.5 this.$backdrop.addClass('in') if (!callback) return //啊,背景div有动画就动画后回调,没有直接回调, 回调是指(显示或关闭逻辑) doAnimate ? this.$backdrop.one('bsTransitionEnd', callback).emulateTransitionEnd(150) : callback() } else if (!this.isShown && this.$backdrop) {
//状态为未显示,且要背景div //去掉半透明效果 this.$backdrop.removeClass('in') //回调函数: 移除遮罩div后回调 var callbackRemove = function () { that.removeBackdrop() callback && callback() } //啊,能动画,就动画后回调上面的函数 $.support.transition && this.$element.hasClass('fade') ? this.$backdrop.one('bsTransitionEnd', callbackRemove) .emulateTransitionEnd(150) : callbackRemove() } else if (callback) {
//显示但是不要背景div,且回调不为空,这里回调是显示model逻辑 callback() } } //检查是否有滚动条,并计算滚动条宽度(猜的-.-!) Modal.prototype.checkScrollbar = function() { if (document.body.clientWidth >= window.innerWidth) return this.scrollbarWidth = this.scrollbarWidth || this.measureScrollbar() } //设置又内边距(估计和滚动条有关) Modal.prototype.setScrollbar = function() { var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10) if (this.scrollbarWidth) this.$body.css('padding-right', bodyPad + this.scrollbarWidth) } //还原上面内边距设置 Modal.prototype.resetScrollbar = function() { this.$body.css('padding-right', '') } //猜测是计算滚动条宽度的一种方法 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 // ======================= //对model的包装,支持批量操作,缓存,配置合并,方法调用, //option:model配置, _relatedTarget:show.bs.modal和shown.bs.modal事件的关联relatedTarget function Plugin(option, _relatedTarget) { return this.each(function () { var $this = $(this) //取缓存model对象 var data = $this.data('bs.modal')//缓存 //合并配置参数 var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option) //缓存没有,就new一个model if (!data) $this.data('bs.modal', (data = new Modal(this, options))) //如果参数为字符串(一般是'toggle','show','hien') if (typeof option == 'string') data[option](_relatedTarget) //如果配置为初始显示,就显示 else if (options.show) data.show(_relatedTarget) }) } //保存老的model属性,防冲突 var old = $.fn.modal //导出 $.fn.modal = Plugin $.fn.modal.Constructor = Modal // MODAL NO CONFLICT // ================= //有冲突时,还原$.fn.modal的引用,然后返回自己 $.fn.modal.noConflict = function () { $.fn.modal = old return this } // MODAL DATA-API // ============== //为保护[data-toggle="modal"]属性的元素绑定单击事件:click.bs.modal.data-api //例如链接\ //对应上面的元素,插件就会为它绑定单击事件,使用$('#model1')来加载href,然后显示,我这里碰到,多次点击会产生多层背景div的问题,等有时间找找原因 $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) { var $this = $(this) var href = $this.attr('href') //通过jq获取对应的model元素(根据当前元素data-target属性 或 href属性) var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7 //model元素有缓存 ? 直接调用toggle方法 : 没有就远程获取href内容显示 var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data()) //阻止a标签浏览器默认行为 if ($this.is('a')) e.preventDefault() //为model绑定show.bs.modal(显示前)事件 $target.one('show.bs.modal', function (showEvent) { //如果前面注册的事件处理器一定调用了preventDefault方法,就不会显示,后面也就不绑定隐藏事件了,所以这里也不要处理了. if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown //为model绑定hidden.bs.modal(隐藏后)事件, 如果当前元素可见,就触发当前元素焦点事件 $target.one('hidden.bs.modal', function () { $this.is(':visible') && $this.trigger('focus') }) }) //调用Model.toggle方法,或者创建新的model对象,并从远处加载内容 Plugin.call($target, option, this) }) }(jQuery);

 

转载地址:http://acesl.baihongyu.com/

你可能感兴趣的文章
自学社交的人工智能,会不会有一天取人类而代之?
查看>>
centos 6.5下安装fpm打包工具
查看>>
微信的视频如何找到文件并发送到电脑
查看>>
ionic react-native和native开发移动app到底那个好
查看>>
Grid_Oracle Grid Infrastructure概念介绍(概念)
查看>>
分布式全局锁
查看>>
谈谈17年工业届三个热点词汇的个人见解
查看>>
VMware vSphere 6.5 配置文档
查看>>
LINUX学习(LINUX就该这么学)2
查看>>
PostgreSQL系列产品云生态、产品指南、企业全栈应用案例、开发管理实践
查看>>
linux内核启动_学习笔记
查看>>
linux下samba共享中文乱码解决办法
查看>>
HSRP热备份
查看>>
pfSense通过别名限制迅雷下载
查看>>
软件自动化测试资源列表
查看>>
数字签名与数字证书技术简介
查看>>
[LNMP]Nginx解析php与代理
查看>>
GridView动态添加新行
查看>>
使用Kazoo去增删改查zookeeper
查看>>
C# 实现系统关机、注销、重启、休眠、挂起
查看>>