Bootstrap模态窗口源码解析
前言:
bootstrap的 js插件的源码写的非常好,也算是编写jquery插件的模范写法,本来还想大篇详细的分析一下呢,唉,没时间啊,很早之前看过的源码了,现在贴在了博客上,
300来行的代码,其中有很多jquery的高级用法,建议,从github上下载一下源码,然后把本篇的代码复制过去,然后,边运行,边阅读,如果有不明白的地方,可以给我留言,我给解答。
下面是基本每行都加了注释,供大家参考,具体内容如下
/* ======================================================================== * Bootstrap: modal.js v3.3.7 * http://www.php.cn/ * ======================================================================== * Copyright 2011-2016 Twitter, Inc. * Licensed under MIT (http://www.php.cn/) * ======================================================================== */ +function ($) { 'use strict'; // MODAL CLASS DEFINITION // ====================== var Modal = function (element, options) {//modal类:首先是Modal的构造函数,里面声明了需要用到的变量,随后又设置了一些常量。 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//忽略遮罩成点击吗,不忽略,即:点击遮罩层退出模态 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.7' Modal.TRANSITION_DURATION = 300 //transition duration 过度时间 Modal.BACKDROP_TRANSITION_DURATION = 150 //背景过度时间 Modal.DEFAULTS = {//defaults 默认值 backdrop: true,//有无遮罩层 keyboard: true,//键盘上的 esc 键被按下时关闭模态框。 show: true//模态框初始化之后就立即显示出来。 } //变量设置完毕,接着就该上函数了。Modal的扩展函数有这么几个: //toggel,show,hide,enforceFocus,escape,resize,hideModal,removeBackdrop, //backdrop,handleUpdate,adjustDialog,resetAdjustments,checkScrollbar,setScrollbar,resetScrollbar, //measureScrollbar终于列完了,恩一共是16个。toggel函数比较简单,是一个显示和隐藏的切换函数。代码如下 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 })//触发 尾行注册的show.bs.modal事件,并给relatedTarget赋值 $.Event 创建事件对象的目的就是可以给他任意赋值 this.$element.trigger(e)// if (this.isShown || e.isDefaultPrevented()) return//如果已经显示就返回 this.isShown = true//标记 this.checkScrollbar()//核对是否有滚动条,并且测量滚动条宽度(非x轴) this.setScrollbar()//如果有滚动条,就给body一个padding-right 是一个滚动条的宽度,这一步的目的是为了呼应,下面的去掉y轴滚动条 this.$body.addClass('modal-open')//接着为body元素添加modal-open类、即去掉y轴滚动条,页面就会往右一个滚动条的宽度, this.escape()//按esc退出模态 this.resize()//窗口大小调整,窗口大小改变,模态框也跟着变 this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))//注册右上角关闭事件 this.$dialog.on('mousedown.dismiss.bs.modal', function () {//在dialog中按下鼠标,在父元素中抬起 忽略: 在模态中按下鼠标,在遮罩层中抬起鼠标 that.$element.one('mouseup.dismiss.bs.modal', function (e) {//在父元素中抬起 if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true }) }) this.backdrop(function () {//遮罩层:真的是一个压轴函数,,,, 这个回调函数是遮罩完毕后运行的函数 var transition = $.support.transition && that.$element.hasClass('fade') if (!that.$element.parent().length) { that.$element.appendTo(that.$body) // don't move modals dom position } that.$element .show() .scrollTop(0)//show 并且 弄到顶部 that.adjustDialog()//调整对话框 if (transition) { that.$element[0].offsetWidth // force reflow } 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 () { that.$element.trigger('focus').trigger(e)//模态过度完成后,触发foucus 和shown.bs.modal }) .emulateTransitionEnd(Modal.TRANSITION_DURATION) : that.$element.trigger('focus').trigger(e)//否则直接进行 }) } Modal.prototype.hide = function (e) {//他的存在就是一个事件监听函数,所以可以加e 下面是模态窗口关闭处理函数 if (e) e.preventDefault()//取消默认行为 e = $.Event('hide.bs.modal')//无论什么事件进入这里都换成 'hide.bs.modal' 妈的这样就通用了,,,无论是点击“x”,还是取消,确定,都这么处理, this.$element.trigger(e)//处发hide if (!this.isShown || e.isDefaultPrevented()) return this.isShown = false//恢复初始的false this.escape()//移除esc事件 this.resize()//移除为window绑定的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))//到了这里,虽然模态已经没有了,但仅仅是把透明度改为0了,this.hideModal才是真正移除 .emulateTransitionEnd(Modal.TRANSITION_DURATION) : this.hideModal() } Modal.prototype.enforceFocus = function () {//模态框获得焦点 $(document) .off('focusin.bs.modal') // guard against infinite focus loop .on('focusin.bs.modal', $.proxy(function (e) { if (document !== e.target && this.$element[0] !== e.target && !this.$element.has(e.target).length) { this.$element.trigger('focus') } }, this)) } Modal.prototype.escape = function () {//键盘上的 esc 键被按下时关闭模态框。 if (this.isShown && this.options.keyboard) {//仅在模态窗显示的时候才注册这个事件 this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {//不仅可以把事件穿过来,。。。牛 e.which == 27 && this.hide()//27 时调用hide方法(ps:比if省事多了,高手就是高手) }, this)) } else if (!this.isShown) {//否则移除他,感觉怪怪的,不管了 this.$element.off('keydown.dismiss.bs.modal') } } Modal.prototype.resize = function () {//为你window resize注册事件 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 } Modal.prototype.backdrop = function (callback) { var that = this var animate = this.$element.hasClass('fade') ? 'fade' : ''//是否有fade动画类 if (this.isShown && this.options.backdrop) {//条件:正在show,并且有遮罩层 var doAnimate = $.support.transition && animate// do的条件是支持css3过度和有fade class this.$backdrop = $(document.createElement('p'))//创建遮罩层p .addClass('modal-backdrop ' + animate)//添加 modal-backdrop 和fade class .appendTo(this.$body)//加到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')//添加in 0.5的透明度 if (!callback) return doAnimate ? this.$backdrop .one('bsTransitionEnd', callback) .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) ://如果有fade动画的话 就给遮罩层绑定一个遮罩过度时间,为什么要这么写以后聊 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 () {//用来为body元素设置padding-right的值,防止body的元素被scrollbar阻挡 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 测量 Scrollbar var scrollp = document.createElement('p') scrollp.className = 'modal-scrollbar-measure' this.$body.append(scrollp) var scrollbarWidth = scrollp.offsetWidth - scrollp.clientWidth this.$body[0].removeChild(scrollp) 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)))//把modal对象存起来,避免第二次打开时在new对象,这点值得学习 if (typeof option == 'string') data[option](_relatedTarget)/*这里是区分option是对象和字符串的情况*/ 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 这里是不用一行js代码就实现modal的关键 // ============== $(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())//这地方是区别一下第一次触发和第二次触发 //到这里为止是为了得到被控制的modal的dom元素 if ($this.is('a')) e.preventDefault() $target.one('show.bs.modal', function (showEvent) {//调用show方法后立即执行的事件 if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown $target.one('hidden.bs.modal', function () {//调用show后创建的事件,模态框隐藏后触发, $this.is(':visible') && $this.trigger('focus')//如果原来的按钮还存在的(或显示的)话,那就让他得到焦点 }) }) Plugin.call($target, option, this) }) }(jQuery);
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持PHP中文网。
更多Bootstrap模态窗口源码解析相关文章请关注PHP中文网!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Cara menggunakan Bootstrap untuk mendapatkan nilai bar carian: Menentukan ID atau nama bar carian. Gunakan JavaScript untuk mendapatkan elemen DOM. Mendapat nilai elemen. Lakukan tindakan yang diperlukan.

Menggunakan bootstrap dalam vue.js dibahagikan kepada lima langkah: Pasang bootstrap. Import bootstrap di main.js. Gunakan komponen bootstrap secara langsung dalam templat. Pilihan: Gaya tersuai. Pilihan: Gunakan pemalam.

Gunakan Bootstrap untuk melaksanakan pusat menegak: Kaedah Flexbox: Gunakan kelas D-Flex, Justify-Content, dan Align-Item-Center untuk meletakkan unsur-unsur dalam bekas Flexbox. Kaedah Kelas Align-Items-Center: Bagi pelayar yang tidak menyokong Flexbox, gunakan kelas Align-Items-Center, dengan syarat unsur induk mempunyai ketinggian yang ditetapkan.

Terdapat dua cara untuk membuat garis perpecahan bootstrap: menggunakan tag, yang mewujudkan garis perpecahan mendatar. Gunakan harta sempadan CSS untuk membuat garis perpecahan gaya tersuai.

Bagaimana cara menggunakan butang bootstrap? Perkenalkan CSS bootstrap untuk membuat elemen butang dan tambahkan kelas butang bootstrap untuk menambah teks butang

Untuk menyesuaikan saiz unsur-unsur dalam bootstrap, anda boleh menggunakan kelas dimensi, yang termasuk: menyesuaikan lebar: .col-, .w-, .mw-adjust ketinggian: .h-, .min-h-, .max-h-

Untuk menubuhkan rangka kerja bootstrap, anda perlu mengikuti langkah -langkah ini: 1. Rujuk fail bootstrap melalui CDN; 2. Muat turun dan tuan rumah fail pada pelayan anda sendiri; 3. Sertakan fail bootstrap di HTML; 4. Menyusun sass/kurang seperti yang diperlukan; 5. Import fail tersuai (pilihan). Setelah persediaan selesai, anda boleh menggunakan sistem grid Bootstrap, komponen, dan gaya untuk membuat laman web dan aplikasi yang responsif.

Terdapat beberapa cara untuk memasukkan imej dalam bootstrap: masukkan imej secara langsung, menggunakan tag HTML IMG. Dengan komponen imej bootstrap, anda boleh memberikan imej yang responsif dan lebih banyak gaya. Tetapkan saiz imej, gunakan kelas IMG-cecair untuk membuat imej boleh disesuaikan. Tetapkan sempadan, menggunakan kelas IMG-Sempadan. Tetapkan sudut bulat dan gunakan kelas IMG-bulat. Tetapkan bayangan, gunakan kelas bayangan. Saiz semula dan letakkan imej, menggunakan gaya CSS. Menggunakan imej latar belakang, gunakan harta CSS imej latar belakang.
