zoukankan      html  css  js  c++  java
  • 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
      }

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

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

  • 相关阅读:
    UVA 1513
    《ArcGIS Runtime SDK for Android开发笔记》——问题集:.geodatabase创建,创建时内容缺失问题总结
    《ArcGIS Runtime SDK for Android开发笔记》——问题集:使用TextSymbol做标注显示乱码
    《ArcGIS Runtime SDK for Android开发笔记》——(7)、示例代码arcgis-runtime-samples-android的使用
    《ArcGIS Runtime SDK for Android开发笔记》——(6)、基于Android Studio的ArcGIS Android工程结构解析
    《ArcGIS Runtime SDK for Android开发笔记》——(5)、基于Android Studio构建ArcGIS Android开发环境(离线部署)
    《ArcGIS Runtime SDK for Android开发笔记》——(4)、基于Android Studio构建ArcGIS Android开发环境
    《ArcGIS Runtime SDK for Android开发笔记》——(3)、ArcGIS Runtime SDK概述
    《ArcGIS Runtime SDK for Android开发笔记》——(2)、Android Studio基本配置与使用
    《ArcGIS Runtime SDK for Android开发笔记》——(1)、Android Studio下载与安装
  • 原文地址:https://www.cnblogs.com/wumadi/p/3267834.html
Copyright © 2011-2022 走看看