zoukankan      html  css  js  c++  java
  • Bootstrap Dropdown 源码分析

    /* ========================================================================
     * Bootstrap: dropdown.js v3.3.5
     * http://getbootstrap.com/javascript/#dropdowns
     * ========================================================================
     * Copyright 2011-2015 Twitter, Inc.
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
     * ======================================================================== */
    
    
    +function ($) {
      'use strict';
    
      // DROPDOWN CLASS DEFINITION
      // =========================
    
      var backdrop = '.dropdown-backdrop'
      var toggle   = '[data-toggle="dropdown"]'
      var Dropdown = function (element) {
        $(element).on('click.bs.dropdown', this.toggle)
      }
    
      Dropdown.VERSION = '3.3.5'
    
      function getParent($this) {//如果没有指定父元素,那么就是$this的上一级元素
        var selector = $this.attr('data-target')//
    
        if (!selector) {
          selector = $this.attr('href')
          selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^s]*$)/, '') // strip for ie7
        }
    
        var $parent = selector && $(selector)
    
        return $parent && $parent.length ? $parent : $this.parent()
      }
    
      function clearMenus(e) {
        if (e && e.which === 3) return
        $(backdrop).remove()
        $(toggle).each(function () {//遍历每一个触发菜单的元素
          var $this         = $(this)
          var $parent       = getParent($this)
          var relatedTarget = { relatedTarget: this }//哪个元素触发的
    
          if (!$parent.hasClass('open')) return//没有open直接返回
            //点击的是父元素包含的元素,并且还要是input|textarea/i其中的一个
          if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return//有open时满足这几个条件的不处理
    
          $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))//hide 前触发的事件
    
          if (e.isDefaultPrevented()) return//不解释,为了健壮性
    
          $this.attr('aria-expanded', 'false')//搞个标记意思是没展开
          $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)//核心代码,移除open  然后触发hidden.bs.dropdown
        })
      }
    
      Dropdown.prototype.toggle = function (e) {
        var $this = $(this)
    
        if ($this.is('.disabled, :disabled')) return
    
        var $parent  = getParent($this)
        var isActive = $parent.hasClass('open')//是否是有open
    
        clearMenus()//去除所有open
    
        if (!isActive) {//非open状态下处理
          if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
            // if mobile we use a backdrop because click events don't delegate
            $(document.createElement('div'))
              .addClass('dropdown-backdrop')
              .insertAfter($(this))
              .on('click', clearMenus)
          }
    
          var relatedTarget = { relatedTarget: this }
          $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
    
          if (e.isDefaultPrevented()) return
    
          $this
            .trigger('focus')
            .attr('aria-expanded', 'true')
    
          $parent
            .toggleClass('open')
            .trigger('shown.bs.dropdown', relatedTarget)
        }
    
        return false
      }
    
      Dropdown.prototype.keydown = function (e) {
        if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
    
        var $this = $(this)
    
        e.preventDefault()
        e.stopPropagation()
    
        if ($this.is('.disabled, :disabled')) return
    
        var $parent  = getParent($this)
        var isActive = $parent.hasClass('open')
    
        if (!isActive && e.which != 27 || isActive && e.which == 27) {
          if (e.which == 27) $parent.find(toggle).trigger('focus')
          return $this.trigger('click')
        }
    
        var desc = ' li:not(.disabled):visible a'
        var $items = $parent.find('.dropdown-menu' + desc)
    
        if (!$items.length) return
    
        var index = $items.index(e.target)
    
        if (e.which == 38 && index > 0)                 index--         // up
        if (e.which == 40 && index < $items.length - 1) index++         // down
        if (!~index)                                    index = 0
    
        $items.eq(index).trigger('focus')
      }
    
    
      // DROPDOWN PLUGIN DEFINITION
      // ==========================
    
      function Plugin(option) {
        return this.each(function () {
          var $this = $(this)
          var data  = $this.data('bs.dropdown')
    
          if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
          if (typeof option == 'string') data[option].call($this)
        })
      }
    
      var old = $.fn.dropdown
    
      $.fn.dropdown             = Plugin
      $.fn.dropdown.Constructor = Dropdown
    
    
      // DROPDOWN NO CONFLICT
      // ====================
    
      $.fn.dropdown.noConflict = function () {
        $.fn.dropdown = old
        return this
      }
    
    
      // APPLY TO STANDARD DROPDOWN ELEMENTS
      // ===================================
    
      $(document)
        .on('click.bs.dropdown.data-api', clearMenus)//点空白关闭菜单
        .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
        .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
        .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
        .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)
    
    }(jQuery);
  • 相关阅读:
    LeetCode数据库178
    LeetCode数据库181
    LeetCode数据库177
    LeetCode数据库176
    HNOI2003 消防局的设立
    HNOI2001 产品加工
    Luogu P1020 关路灯
    NOIP2004 虫食算
    SP2713 GSS4-Can you answer these queries IV
    APIO2008 免费道路
  • 原文地址:https://www.cnblogs.com/xiaobie123/p/6014314.html
Copyright © 2011-2022 走看看