zoukankan      html  css  js  c++  java
  • Bootstrap插件之 下拉菜单 源码分析~~

    前言

    前前后后写了大概有四十多篇文章了……阅读量 一直都是 3~5的酱紫。评论倒是很稳定 一直都是零。。这怎么行。于是我痛定思痛。分析了一下自己博客的优缺点。

    缺点 1 界面丑

      2 干货少

      3 语言不生动

    优点

      没有……

    接下来要努力把以上三点做好~今天算是开端。。。!!因为今天研究了bootstrap下拉菜单一天吧差不多,而且网上好像没有看到分析bootstrap插件源码的,所以这篇文章质量应该是比以前的要好点的~

    废话结束~~

    正文

    本文知识点

    1 jquery的时间命名空间

    2jquery插件写法

    好了直接上代码 

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link href="../lib/bootstrap-2.3.2/dist/css/bootstrap.css" rel="stylesheet">
    </head>
    <body>
    <nav class="navbar navbar-default" role="navigation">
        <div class="container-fluid">
            <div class="navbar-header">
                <a class="navbar-brand" href="#">菜鸟教程</a>
            </div>
            <div>
                <ul class="nav navbar-nav">
                    <li class="active"><a href="#">iOS</a></li>
                    <li><a href="#">SVN</a></li>
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown">
                            Java
                            <b class="caret"></b>
                        </a>
                        <ul class="dropdown-menu">
                            <li><a href="#">jmeter</a></li>
                            <li><a href="#">EJB</a></li>
                            <li><a href="#">Jasper Report</a></li>
                            <li class="divider"></li>
                            <li><a href="#">分离的链接</a></li>
                            <li class="divider"></li>
                            <li><a href="#">另一个分离的链接</a></li>
                        </ul>
                    </li>
                </ul>
            </div>
        </div>
    </nav>
    
    <button id="btn1">点我</button>
    
    </body>
    
    
    <script src="../lib/jquery-1.11.1.js"></script>
    <script>
        +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.0'
            Dropdown.prototype.toggle = function (e) {//对象方法--切换状态
                var $this = $(this)
    
                if ($this.is('.disabled, :disabled')) return
    
                var $parent = getParent($this)
                var isActive = $parent.hasClass('open')
    
                clearMenus()
    
                if (!isActive) {
                    if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
                        // if mobile we use a backdrop because click events don't delegate
                        $('<div class="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)) 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(.divider):visible a'
                var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + 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')
            }
    
            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
    
                    $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
    
                    if (e.isDefaultPrevented()) return
    
                    $this.attr('aria-expanded', 'false')
                    $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
                })
            }
    
            function getParent($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()
            }
    
    
            // DROPDOWN PLUGIN DEFINITION
            // ==========================
    
            function Plugin(option) {//这里很关键,
                //debugger;
                //console.log(this);这里this是jquery对象
                return this.each(function () {//在本例中 也就是 遍历$(".dropdown-toggle")对应的dom对象  //这里的this是dom对象!!!
                   // console.log(this);
                   // debugger;
                    var $this = $(this)//包装成jquery对象
                    var data = $this.data('bs.dropdown')//第一次肯定没有
    
                    if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))//此处真正的 实例化了Dropdown();
                    if (typeof option == 'string') data[option].call($this)//调用Dropdown实例对象toggole对应的方法!
                })
            }
    
    
            var old = $.fn.dropdown
    
            $.fn.dropdown = Plugin//将方法 暴露出去,外界通过$(".dropdown-toggle").dropdown('toggle');来主动 开关下拉列表
            $.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)//再此处绑定的下拉按钮的点击事件  ps:click.bs.dropdown.data-api 这是什么鬼?请搜索“事件命名空间”
                    .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
                    .on('keydown.bs.dropdown.data-api', '[role="menu"]', Dropdown.prototype.keydown)
                    .on('keydown.bs.dropdown.data-api', '[role="listbox"]', Dropdown.prototype.keydown)
    
        }(jQuery);
    
    </script>
    <script>
    
    
        $(function () {
            // 默认显示
            //$(".dropdown-toggle").dropdown('toggle');
    
            $('#btn1').click(
    
                function (e) {
                    //console.log(this); // ps补充一下 这里this 指向谁?是jquery对象 还是 原生dom的button对象?? 放开注释看一下就知道了~~
                    $(".dropdown-toggle").dropdown('toggle');
                    stopBubble(e);
                }
            );
        });
    
        function stopBubble(e){
            //一般用在鼠标或键盘事件上
            if(e && e.stopPropagation){
                //W3C取消冒泡事件
                e.stopPropagation();
            }else{
                //IE取消冒泡事件
                window.event.cancelBubble = true;
            }
        };
    </script>
    </html>
    View Code

    注释都写得很详细了~如果您有任何疑惑或者发现问题 欢迎随时留言哦~~

  • 相关阅读:
    微软职位内部推荐-Senior SDE
    在使用Fake framework的时候,为什么有一些函数没有生产mock呢?
    Call Azure Queue get "The remote server returned an error: (400) Bad Request."
    技术分享
    IT牛人博客
    Spring-data-redis操作redis cluster
    Spring对Hibernate事务管理【转】
    Hibernate事务管理
    Redis与Memcached对比
    LockSupport的park和unpark
  • 原文地址:https://www.cnblogs.com/WhiteHorseIsNotHorse/p/6271282.html
Copyright © 2011-2022 走看看