Template:USTC-Software/js/autoMenu

/*

* blogMenu plugin 1.0   2017-09-01 by cary
* 说明:自动根据标签(h3,h4)生成博客目录
*/

(function ($) {

   var Menu = (function () {
       /**
        * 插件实例化部分,初始化时调用的代码可以放这里
        * @param element 传入jq对象的选择器,如 $("#J_plugin").plugin() ,其中 $("#J_plugin") 即是 element
        * @param options 插件的一些参数神马的
        * @constructor
        */
       var Plugin = function(element, options) {
           //将dom jquery对象赋值给插件,方便后续调用
           this.$element = $(element);
           //将插件的默认参数及用户定义的参数合并到一个新的obj里
           this.settings = $.extend({}, $.fn.autoMenu.defaults, typeof options === 'object' && options)
           //如果将参数设置在dom的自定义属性里,也可以这样写
           //this.settings = $.extend({}, $.fn.plugin.defaults, this.$element.data(), options);
           this.init();
       }


       /**
        * 将插件所有函数放在prototype的大对象里
        * 插件的公共方法,相当于接口函数,用于给外部调用
        * @type {{}}
        */
       Plugin.prototype = {
           init: function () {
               var opts = this.settings;
               //console.log(opts)
               this.$element.html(this.createHtml());
               this.setActive();
               this.bindEvent();
               
           },
           createHtml: function(){
               var that = this;
               var opts = that.settings;
               var width = typeof opts.width === 'number' && opts.width;
               var height = typeof opts.height === 'number' && opts.height;
               var padding = typeof opts.padding === 'number' && opts.padding;
               that.$element.width(width+padding*2);
// var html = '
    '; var html = '
      '; var num = 0; $('*').each(function(){ var _this = $(this); if(_this.get(0).tagName == opts.levelOne.toUpperCase()){ _this.attr('id',num); var nodetext = that.handleTxt(_this.html()); html += '
    • <a href="#'+ num +'">'+ nodetext +'</a>
    • ';
                             num++;
                         }else if(_this.get(0).tagName == opts.levelTwo.toUpperCase()){
                             _this.attr('id',num);
                             var nodetext = that.handleTxt(_this.html());
      
      html += '
    • <a href="#'+ num +'">'+ nodetext +'</a>
    • ';
                             num++;
                         }
                     })
      
      html += '
    <a href="javascript:void(0);" class="btn-box">'
                               +''
                           +'</a>';
                   return html;   
               },
               handleTxt: function(txt){
                   //正则表达式去除HTML的标签
                   return txt.replace(/<\/?[^>]+>/g,"").trim();
               },
               setActive: function(){
                   var $el = this.$element,
                       opts = this.settings,
                       items = opts.levelOne + ',' + opts.levelTwo,
                       $items = $(items),
                       offTop = opts.offTop,
                       top = $(document).scrollTop(),
                       currentId;
                   if($(document).scrollTop()==0){
                       //初始化active
                       $el.find('li').removeClass('active').eq(0).addClass('active');
                       return;
                   }
                   $items.each(function(){
                       var m = $(this),
                           itemTop = m.offset().top;
                       if(top > itemTop-offTop){
                           currentId = m.attr('id');
                       }else{
                           return false;
                       }
                   })
                   var currentLink = $el.find('.active');
                   if(currentId && currentLink.attr('name')!= currentId){
                     currentLink.removeClass('active');
                     $el.find('[name='+currentId+']').addClass('active');
                   }
                   
               },
               bindEvent: function(){
                   var _this = this;
                   $(window).scroll(function(){
                       _this.setActive()
                   });
                   _this.$element.on('click','.btn-box',function(){
                       if($(this).find('span').hasClass('icon-minus-sign')){
                           $(this).find('span').removeClass('icon-minus-sign').addClass('icon-plus-sign');
                           _this.$element.find('ul').fadeOut();
                       }else{
                           $(this).find('span').removeClass('icon-plus-sign').addClass('icon-minus-sign');
                           _this.$element.find('ul').fadeIn();
                       }
                       
                   })
               }
    
           };
    
           return Plugin;
    
       })();
    


       /**
        * 这里是将Plugin对象 转为jq插件的形式进行调用
        * 定义一个插件 plugin
        */
       $.fn.autoMenu = function (options) {
           return this.each(function () {
               var $el = $(this),
                   menu = $el.data('autoMenu'),
                   option = $.extend({}, $.fn.autoMenu.defaults, typeof options === 'object' && options);
               if (!menu) {
                   //将实例化后的插件缓存在dom结构里(内存里)
                   $el.data('autoMenu',new Menu(this, option));
               }
    
               /**
                * 如果插件的参数是一个字符串,则 调用 插件的 字符串方法。
                * 如 $('#id').plugin('doSomething') 则实际调用的是 $('#id).plugin.doSomething();
                */
               if ($.type(options) === 'string') menu[option]();
           });
       };
    
       /**
        * 插件的默认值
        */
       $.fn.autoMenu.defaults = {
           levelOne : 'h3', //一级标题
           levelTwo : 'h4',  //二级标题(暂不支持更多级)
           width : 270, //容器宽度
           height : 800, //容器高度
           padding: 20, //内部间距
           offTop : 100, //滚动切换导航时离顶部的距离
    
       };
    
       /**
        * 优雅处: 通过data-xxx 的方式 实例化插件。
        * 这样的话 在页面上就不需要显示调用了。
        * 可以查看bootstrap 里面的JS插件写法
        */
       $(function () {
           if($('[data-autoMenu]').length>0){
               if($(window).width() > 986){
                   new Menu($('[data-autoMenu]'));
               }
           }
           
       });
    
    })(jQuery);