Bootstrap的Model源码详细注释

工作中用到了Bootstrap的Model这个插件,想封装下,然后看了下源码不多,于是读了下源码并注释了下.

后端狗,前端不熟,注释的不好,请务必指出. 

1/* ======================================================================== 2 * Bootstrap: modal.js v3.2.0 3 * http://getbootstrap.com/javascript/#modals 4 * ======================================================================== 5 * Copyright 2011-2014 Twitter, Inc. 6 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 7 * ======================================================================== */ 8 9//这里的 +function($){}(jQuery) 和 (function($){})(jQuery) 一个意思 10+function($) { 11 'use strict'; 12 13 // MODAL CLASS DEFINITION 14 // ====================== 15 16 var Modal = function(element, options) { 17 this.options = options 18 this.$body = $(document.body) 19 this.$element = $(element) 20 this.$backdrop = this.isShown = null 21 this.scrollbarWidth = 0 22 23 // 如果是远程内容,就加载,并触发loaded.bs.modal事件 24 if (this.options.remote) { 25 this.$element.find('.modal-content').load(this.options.remote, 26 $.proxy(function() { 27 this.$element.trigger('loaded.bs.modal') 28 }, this)) 29 } 30 } 31 32 Modal.VERSION = '3.2.0' 33 34 // 默认配置 35 Modal.DEFAULTS = { 36 backdrop : true, // 默认配置,要背景div(单击触发hide方法) 37 keyboard : true, // 要desc键按了就消失的功能 38 show : true // 模态框初始化之后就立即显示出来 39 } 40 41 // 如果是显示的状态,就隐藏,如果是未显示,则显示 42 Modal.prototype.toggle = function(_relatedTarget) { 43 return this.isShown ? this.hide() : this.show(_relatedTarget) 44 } 45 46 // 显示弹出框方法 47 Modal.prototype.show = function(_relatedTarget) { 48 var that = this 49 var e = $.Event('show.bs.modal', {relatedTarget : _relatedTarget}) 50 51     this.$element.trigger(e)// 触发show.bs.modal事件 52 53     // 如果已经显示了, 或者上面事件回调中调用了e.preventDefault 就 直接不处理,直接返回 54 if (this.isShown || e.isDefaultPrevented()) return 55 56     //改变显示状态为显示中 57     this.isShown = true 58 59     //有滚动条的话,就设置滚动条的宽度 60     this.checkScrollbar() 61     //overflow:hidden 62     this.$body.addClass('modal-open') 63     //padding-right 属性在原来的基础上 + 上面算出来的滚动条的宽度 64     this.setScrollbar() 65      66     //如果options.keyboard配置为true则监听keyup.dismiss.bs.modal事件, 功能就是按esc键,就调用hide方法 67     this.escape() 68 69     //为包含data-dismiss="modal"属性的元素注册关闭处理器(比如点x按钮,就隐藏模态框功能) 70     this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this)) 71 72     //backdrop函数:背景逻辑, 回调函数功能:显示model逻辑 73     this.backdrop(function () { 74 // 浏览器是否支持动画 & model的元素包含fade class 75 var transition = $.support.transition && that.$element.hasClass('fade') 76 77 // 没有父元素(例:还未append的$("<div></div>")),则将model附加到body上, 78 if (!that.$element.parent().length) { 79 that.$element.appendTo(that.$body) // don't move modals dom position 80 } 81          82         // 将model元素设置成显示(jq.show方法), 并移动到最上面 83         that.$element.show().scrollTop(0) 84 85         //动画效果准备 86         if (transition) { 87             that.$element[0].offsetWidth // force reflow 88         } 89 90         //设置不透明opacity:1, 设置显示(aria,给不方便人士用的)aria-hidden:false 91         that.$element.addClass('in').attr('aria-hidden', false); 92          93         //解绑并为document对象注册focusin.bs.modal事件, 具体处理是:如果不是model产生的,就触发model的facus事件 94         //简单的说,就是聚焦,哈哈,看着我,看着我 95         that.enforceFocus() 96 97         //准备触发shown.bs.modal事件 98         var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) 99          100         //有动画,就动画完成后触发focus事件和shown.bs.modal事件 101         transition ? 102         that.$element.find('.modal-dialog') // wait for modal to slide in 103             .one('bsTransitionEnd', function () { 104                 that.$element.trigger('focus').trigger(e) 105             }) 106             .emulateTransitionEnd(300) : 107             that.$element.trigger('focus').trigger(e) 108     }) 109 } 110 111 //隐藏model方法 112 Modal.prototype.hide = function(e) { 113 if (e) e.preventDefault() //不清楚作用场景 114 115 //准备触发隐藏事件, 并触发 116= $.Event('hide.bs.modal') 117 this.$element.trigger(e) 118 119 //如果model状态以及为未显示 或者上面事件回调函数中调用了preventDefault, 就不处理 120 if (!this.isShown || e.isDefaultPrevented()) return 121 122 //设置状态为不显示 123 this.isShown = false 124 125 //去掉显示时加上的class, 具体就是overflow:hidden 126 this.$body.removeClass('modal-open') 127 128 //还原padding-right属性 设置为'' (对应show中的setScrollbar)  129 this.resetScrollbar() 130 131 ////解除keyup.dismiss.bs.modal, 与show方法里的对应 132 this.escape() 133 134 //解除document对象的focusin.bs.modal事件绑定, (对应show中enforceFocus) 135 $(document).off('focusin.bs.modal') 136 137 //移除不透明设置(in), 设置为隐藏, 移除关闭处理器(比如点x按钮,就隐藏模态框功能) 138 this.$element.removeClass('in').attr('aria-hidden', true).off('click.dismiss.bs.modal') 139 140 //动画,然后调用hideModal方法(加上背景div的关联处理) 141 $.support.transition && this.$element.hasClass('fade') ? this.$element 142 .one('bsTransitionEnd', $.proxy(this.hideModal, this)) 143 .emulateTransitionEnd(300) : this.hideModal() 144 } 145 146 //解绑并为document对象注册focusin.bs.modal事件, 具体处理是:如果不是model产生的,就触发model的facus事件 147 Modal.prototype.enforceFocus = function () { 148 $(document).off('focusin.bs.modal') // guard against infinite focus loop 149 .on('focusin.bs.modal', $.proxy(function (e) { 150 if (this.$element[0] !== e.target && !this.$element.has(e.target).length) { 151 this.$element.trigger('focus') 152 } 153 }, this)) 154 } 155 156 //实现按下esc键时,隐藏model功能,(根据配置) 157 Modal.prototype.escape = function () { 158 if (this.isShown && this.options.keyboard) { 159 this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) { 160 e.which == 27 && this.hide() 161 }, this)) 162 } else if (!this.isShown) { 163 this.$element.off('keyup.dismiss.bs.modal') 164 } 165 } 166 167 //隐藏关联方法,隐藏元素,并处理背景div,并触发隐藏完成事件 168 Modal.prototype.hideModal = function () { 169 var that = this 170 //隐藏model自身(jq.hide) 171 this.$element.hide() 172 //隐藏背景逻辑 173 this.backdrop(function () { 174 //触发隐藏完成事件 175 that.$element.trigger('hidden.bs.modal') 176 }) 177 } 178 179 //移除背景div 180 Modal.prototype.removeBackdrop = function () { 181 this.$backdrop && this.$backdrop.remove() 182 this.$backdrop = null 183 } 184 185 //callback为具体的model的隐藏或显示逻辑,backdrop负责背景div逻辑 186 Modal.prototype.backdrop = function (callback) { 187 var that = this 188     189 //是否包含fade样式(动画) 190 var animate = this.$element.hasClass('fade') ? 'fade' : '' 191 192 //如果为显示中 且 要背景div 193 if (this.isShown && this.options.backdrop) { 194 var doAnimate = $.support.transition && animate 195 196 //添加背景div 197 this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />').appendTo(this.$body) 198 199 //绑定click.dismiss.bs.modal事件,  200 this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) { 201 //冒泡来的事件不管,不过一般model都在最外面,so,这里一般不会返回false; 202 if (e.target !== e.currentTarget) return 203 204 //如果backdrop配置参数为static, 则获取焦点,否则,调用隐藏方法 205 this.options.backdrop == 'static' ? this.$element[0].focus.call(this.$element[0]) : this.hide.call(this) 206 }, this)) 207 208 //准备动画 209 if (doAnimate) this.$backdrop[0].offsetWidth // force reflow 210 211 //设置背景div半透明opacity:0.5 212 this.$backdrop.addClass('in') 213 214 if (!callback) return 215 216 //啊,背景div有动画就动画后回调,没有直接回调, 回调是指(显示或关闭逻辑) 217 doAnimate ? this.$backdrop.one('bsTransitionEnd', callback).emulateTransitionEnd(150) : callback() 218 219 } else if (!this.isShown && this.$backdrop) {//状态为未显示,且要背景div 220 //去掉半透明效果 221 this.$backdrop.removeClass('in') 222 223 //回调函数: 移除遮罩div后回调 224 var callbackRemove = function () { 225 that.removeBackdrop() 226 callback && callback() 227 } 228 229 //啊,能动画,就动画后回调上面的函数 230 $.support.transition && this.$element.hasClass('fade') ? 231 this.$backdrop.one('bsTransitionEnd', callbackRemove) 232 .emulateTransitionEnd(150) : callbackRemove() 233 234 } else if (callback) {//显示但是不要背景div,且回调不为空,这里回调是显示model逻辑 235 callback() 236 } 237 } 238 239 //检查是否有滚动条,并计算滚动条宽度(猜的-.-!) 240 Modal.prototype.checkScrollbar = function() { 241 if (document.body.clientWidth >= window.innerWidth) return 242 this.scrollbarWidth = this.scrollbarWidth || this.measureScrollbar() 243 } 244 245 //设置又内边距(估计和滚动条有关) 246 Modal.prototype.setScrollbar = function() { 247 var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10) 248 if (this.scrollbarWidth) this.$body.css('padding-right', bodyPad + this.scrollbarWidth) 249 } 250 251 //还原上面内边距设置 252 Modal.prototype.resetScrollbar = function() { 253 this.$body.css('padding-right', '') 254 } 255 256 //猜测是计算滚动条宽度的一种方法 257 Modal.prototype.measureScrollbar = function() { // thx walsh 258 var scrollDiv = document.createElement('div') 259 scrollDiv.className = 'modal-scrollbar-measure' 260 this.$body.append(scrollDiv) 261 var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth 262 this.$body[0].removeChild(scrollDiv) 263 return scrollbarWidth 264 } 265 266 267 // MODAL PLUGIN DEFINITION 268 // ======================= 269 270 //对model的包装,支持批量操作,缓存,配置合并,方法调用, 271 //option:model配置,   _relatedTarget:show.bs.modal和shown.bs.modal事件的关联relatedTarget 272 function Plugin(option, _relatedTarget) { 273 return this.each(function () { 274 var $this   = $(this) 275 //取缓存model对象 276 var data    = $this.data('bs.modal')//缓存 277 //合并配置参数 278 var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option) 279 280 //缓存没有,就new一个model 281 if (!data) $this.data('bs.modal', (data = new Modal(this, options))) 282 //如果参数为字符串(一般是'toggle','show','hien') 283 if (typeof option == 'string') data[option](_relatedTarget) 284 //如果配置为初始显示,就显示 285 else if (options.show) data.show(_relatedTarget) 286 }) 287 } 288 289 //保存老的model属性,防冲突 290 var old = $.fn.modal 291 292 //导出 293 $.fn.modal             = Plugin 294 $.fn.modal.Constructor = Modal 295 296 297 // MODAL NO CONFLICT 298 // ================= 299 300 //有冲突时,还原$.fn.modal的引用,然后返回自己 301 $.fn.modal.noConflict = function () { 302 $.fn.modal = old 303 return this 304 } 305 306 307 // MODAL DATA-API 308 // ============== 309 310 //为保护[data-toggle="modal"]属性的元素绑定单击事件:click.bs.modal.data-api 311 //例如<a data-toggle="modal" data-target="#model1" href="http://localhost:8080/ysdai-mobile/">链接</a>\ 312 //对应上面的元素,插件就会为它绑定单击事件,使用$('#model1')来加载href,然后显示,我这里碰到,多次点击会产生多层背景div的问题,等有时间找找原因 313 $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) { 314 var $this   = $(this) 315 var href    = $this.attr('href') 316 //通过jq获取对应的model元素(根据当前元素data-target属性 或 href属性) 317 var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7 318 //model元素有缓存 ? 直接调用toggle方法 : 没有就远程获取href内容显示 319 var option  = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data()) 320 321 //阻止a标签浏览器默认行为 322 if ($this.is('a')) e.preventDefault() 323 324 //为model绑定show.bs.modal(显示前)事件 325 $target.one('show.bs.modal', function (showEvent) { 326 //如果前面注册的事件处理器一定调用了preventDefault方法,就不会显示,后面也就不绑定隐藏事件了,所以这里也不要处理了. 327 if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown 328 329 //为model绑定hidden.bs.modal(隐藏后)事件, 如果当前元素可见,就触发当前元素焦点事件 330 $target.one('hidden.bs.modal', function () { 331 $this.is(':visible') && $this.trigger('focus') 332 }) 333 }) 334 335 //调用Model.toggle方法,或者创建新的model对象,并从远处加载内容 336 Plugin.call($target, option, this) 337 }) 338 339}(jQuery);
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

java将前端的json数组字符串转换为列表

记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang