美文网首页
关于侧边栏滚动导航事件

关于侧边栏滚动导航事件

作者: 王二麻子88 | 来源:发表于2020-12-04 11:07 被阅读0次

侧边栏滚动导航事件

// TODO

$(function() {
    var ctrl = {
        scrollHandler: function() {
            var self = this;
            var win = $(window);
            var docs = $('.docs');
            var navContainer = $('#J-nav');
            var navItem = $('.nav-section-item');
            // heaerHeight 除外其他的干扰因素, outerHeight属性是计算包含内外边距在内的高度
            var headerHeight = $('.documentation').outerHeight() + $('.topbar').outerHeight();

            // 设置位置参数列表, 包含每个锚点距离正文顶部的高度
            var positions = [];
            // h3是标记标签
            $('h3', docs).each(function() {
                var current = $(this);
                var text = current.text();
                var anchor = text.split(' ')[0];

                positions.push(parseInt(current.offset().top));  // 获取每个锚点距离正文的高度
                navItem.filter('[href="#'+ anchor +'"]').attr('rel', positions.length - 1);

            });

            var positionLength = positions.length;
            // 设置防抖节点, 在一定时间内滚动不做处理
            var timer;

            // 监听window的滚动事件
            win.scroll(function() {
                // 获取正文被卷去的高度
                var scrollTop = win.scrollTop();

                navContainer.css('top', scrollTop >= headerHeight ? 0 : Math.min(headerHeight, headerHeight - scrollTop));
                // 防止重复设置侧边整体的位置
                if (self.noscroll) {
                    self.noscroll = false;
                    return;
                }

                // 延迟函数是防抖的写法, 延迟函数内部才是主要内容
                if (timer) clearTimeout(timer);
                timer = setTimeout(function() {
                    for (var i = 0; i < positionLength; i++) {
                        if (scrollTop < positions[0]) {
                            self.backNav();
                            return;
                        }

                        if ( (positions[i] <= scrollTop) && (positions[i + 1] > scrollTop) ) {
                            self.selectNav(i);
                        }
                    }
                }, 50);
            });

            // 主动触发某个事件
            win.trigger('scroll');
        },

        // 设置观察者事件==> 监听各种点击事件
        observer: function() {
            var self = this;

            self.addAnchors();  // 添加
            self.addNav();  // 生成侧边的导航栏

            var navItem = $('.nav-section-item');
            var navTitle = $('.nav-section-title');
            var gotoTop = $('#gototop');

            // 点击侧边子标题事件
            navItem.on('click', function() {
                var current = $(this);
                var index = current.attr('rel');

                navItem.removeClass('active');
                current.addClass('active');

                self.selectNav(index);
            });

            // 点击侧边栏主标题事件
            navTitle.on('click', function() {
                var current = $(this);
                self.selectNav(current.next().attr('rel'));
                self.noscroll = true;
            });

            // 返回顶部事件
            gotoTop.on('click', function() {
                $('body').get(0).scrollTop = 0;
            });

            // 注册滚动监听事件
            self.scrollHandler();

        },

        // add anchors 生成正文的锚点标签
        addAnchors: function() {
            var docs = $('.docs');

            $('h3', docs).each(function() {
                var current = $(this);
                var anchor = current.text().split(' ')[0];

                current.before('<a name="'+ anchor +'"></a>');
            });
        },

        // add nav
        addNav: function() {
            var docs = $('.docs');
            var navContainer = $('#J-nav');
            var newNav = '';

            var hash = (function() {
                var result = {};
                var currentItem;

                $('h1, h2, h3', docs).each(function() {
                    var current = $(this);
                    var tagName = this.tagName.toLowerCase();  // 标签转小写
                    var text = current.text();
                    var anchor = text.split(' ')[0];

                    if (tagName === 'h1') {
                        if (text !== 'Constructor' && text !== 'Configuring Defaults') {
                            currentItem = result[text] = result[text] || [];
                            current.before('<a name="'+ text.replace(' ', '') +'"></a>');
                        }
                    }
                    else if (tagName === 'h2') {
                        currentItem = result[text] = result[text] || [];
                        current.before('<a name="'+ text.replace(' ', '') +'"></a>');
                    }
                    else if (tagName === 'h3') {
                        currentItem.push(anchor);
                    }
                });

                return result;
            })();

            for (var cat in hash) {
                if (hash.hasOwnProperty(cat)) {
                    newNav += '<div class="nav-section">';
                    newNav += '<div class="nav-section-title"><a href="#'+ cat.replace(' ', '') +'">'+ cat +'<\/a><\/div>';

                    $.each(hash[cat], function(index, name) {
                        newNav += '<a class="nav-section-item" href="#'+ name +'">'+ name +'<\/a>';
                    });

                    newNav += '<\/div>';
                }
            }

            navContainer.html(newNav);
        },

        // select nav
        selectNav: function(index) {
            var navContainer = $('#J-nav');
            var navItem = $('.nav-section-item', navContainer);

            navItem.eq(navContainer.data('menuon')).removeClass('active').parent().removeClass('active');
            navItem.eq(index).addClass('active').parent().addClass('active');
            navContainer.data('menuon', index);
        },

        // nav init
        backNav: function() {
            var navContainer = $('#J-nav');
            var navSection = $('.nav-section', navContainer);
            var navItem = $('.nav-section-item', navContainer);

            navSection.removeClass('active');
            navItem.removeClass('active');

            navSection.eq(0).addClass('active');

            navContainer.data('menuon', 0);
        },

        // 插入 皮肤事件
        insertSkin: function() {
            var skindemo = $('#J-skin-demo');  //  这是一个用 display: none 制作的模板
            var h1 = $('h1');

            h1.each(function() {
                var current = $(this);

                if (current.text() === 'Skin') {
                    // 标记物后面插入模板
                    current.next().after(skindemo);
                    // 将模板显示出来
                    skindemo.removeAttr('style');
                }
            });
        },

        prettyprint: function() {
            $('pre').addClass('prettyprint linenums');

            window.prettyPrint && prettyPrint();
        },

        // 初始化标签
        init: function() {
            ctrl.observer();
            ctrl.prettyprint();
            ctrl.insertSkin();
        }
    };

    ctrl.init();
});

html部分:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div class="docs">
        <div class="nav" id="J-nav">
            <div class="nav-section active">
                <div class="nav-section-title">Attributes</div>
                <a class="nav-section-item active" href="#header">header</a>
                <a class="nav-section-item" href="#footer">footer</a>
                <a class="nav-section-item" href="#dataSource">dataSource</a>
                <a class="nav-section-item" href="#locator">locator</a>
            </div>
            <div class="nav-section">
                <div class="nav-section-title">Methods</div>
                <a class="nav-section-item">previous</a>
                <a class="nav-section-item">next</a>
            </div>
        </div>
        <div class="content">
            <!-- h1 算是一整页的内容 -->
            <h1>Constructor</h1>
            <!-- h2 是一级标题 -->
            <a name="Commonlyused"></a>
            <h2>Commonly used</h2>
            <!-- h3 是二级标题 -->
            <a name="dataSource"></a>
            <h3>dataSource <em>array | string | object | function</em></h3>
        </div>
    </div>
    <!-- 返回顶部的图标 -->
    <div id="gototop">Top</div>
</body>
</html>

相关文章

网友评论

      本文标题:关于侧边栏滚动导航事件

      本文链接:https://www.haomeiwen.com/subject/ywibwktx.html