如何使用Bootstrap ScrollSpy在body上使用多个目标

时间:2014-05-28 17:26:39

标签: jquery twitter-bootstrap multiple-instances scrollspy

我想使用带有多个导航的Bootstrap ScrollSpy,我的主导航和垂直子挡。

我尝试了多种方式:

  • <body data-spy="scroll" data-target="#main-nav #subnav">
  • <body data-spy="scroll" data-target="#main-nav, #subnav">
  • $('body').scrollspy({target: "#main-nav"});
    $('body').scrollspy({target: "#subnav"});
  • $('body').scrollspy({target: "#main-nav"}, {target: "#subnav"});
  • 放置包装div:
    <body data-spy="scroll" data-target="#main-nav"><div data-spy="scroll" data-target="#subnav">

但没有什么工作正常......

我怎样才能实现这个目标?

谢谢!

2 个答案:

答案 0 :(得分:8)

好的,我找到了实现我想要的方法。

如果我没有定义scrollSpy的目标,我的所有导航链接都会被考虑:

$('body').scrollspy({target: ''});

答案 1 :(得分:1)

我知道,这个问题很老了,但是在这里,我的实现是针对多个目标的滚动间谍。 就像这样使用它:<body data-multiple-spy="scroll" data-target="#bs-example-navbar-collapse-1,#features-navbar .navbar-collapse" data-offset="70"</body>

插件:

+function ($) {
'use strict';

// Multiple SCROLLSPY CLASS DEFINITION
// ===================================

function MultipleScrollSpy(element, options) {
    this.$body = $(document.body)
    this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
    this.options = $.extend({}, MultipleScrollSpy.DEFAULTS, options)
    var target = (this.options.target || '').split(',');
    this.selector = target.map(function (s) { return s + ' .nav li > a' })
    this.offsets = []
    this.targets = []
    this.activeTarget = []
    this.scrollHeight = 0

    this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
    this.refresh()
    this.process()
}

MultipleScrollSpy.VERSION = '0.0.1'

MultipleScrollSpy.DEFAULTS = {
    offset: 10
}

MultipleScrollSpy.prototype.getScrollHeight = function () {
    return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
}

MultipleScrollSpy.prototype.refresh = function () {
    var that = this
    var offsetMethod = 'offset'
    var offsetBase = 0

    this.offsets = []
    this.targets = []
    this.activeTarget = []
    this.scrollHeight = this.getScrollHeight()

    if (!$.isWindow(this.$scrollElement[0])) {
        offsetMethod = 'position'
        offsetBase = this.$scrollElement.scrollTop()
    }

    for (var i = 0; i < this.selector.length; i++) {
        that.offsets[i] = [];
        that.targets[i] = [];
        this.$body
            .find(this.selector[i])
            .map(function () {
                var $el = $(this)
                var href = $el.data('target') || $el.attr('href')
                var $href = /^#./.test(href) && $(href)

                return ($href &&
                    $href.length &&
                    $href.is(':visible') &&
                    [[$href[offsetMethod]().top + offsetBase, href]]) ||
                    null
            })
            .sort(function (a, b) { return a[0] - b[0] })
            .each(function () {
                that.offsets[i].push(this[0])
                that.targets[i].push(this[1])
            })
    }
}

MultipleScrollSpy.prototype.process = function () {
    for (var k = 0; k < this.selector.length; k++) {
        var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
        var scrollHeight = this.getScrollHeight()
        var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
        var offsets = this.offsets[k] || []
        var targets = this.targets[k] || []
        var activeTarget = this.activeTarget[k]
        var i

        if (this.scrollHeight != scrollHeight) {
            this.refresh()
        }

        if (scrollTop >= maxScroll) {
            return activeTarget[k] != (i = targets[targets.length - 1]) && this.activate(k, i)
        }

        if (activeTarget && scrollTop < offsets[0]) {
            this.activeTarget[k] = null
            return this.clear(k)
        }

        for (i = offsets.length; i--;) {
            activeTarget != targets[i] &&
                scrollTop >= offsets[i] &&
                (offsets[i + 1] === undefined || scrollTop < offsets[i + 1]) &&
                this.activate(k, targets[i])
        }
    }
}

MultipleScrollSpy.prototype.activate = function (index, target) {
    this.activeTarget[index] = target

    this.clear(index)

    var selector = this.selector[index] +
        '[data-target="' + target + '"],' +
        this.selector[index] + '[href="' + target + '"]'

    var active = $(selector)
        .parents('li')
        .addClass('active')

    if (active.parent('.dropdown-menu').length) {
        active = active
            .closest('li.dropdown')
            .addClass('active')
    }

    active.trigger('activate.bs.scrollspy')
}

MultipleScrollSpy.prototype.clear = function (index) {
    $(this.selector[index])
        .parentsUntil(this.options.target, '.active')
        .removeClass('active')
}


// MULTIPLE SCROLLSPY PLUGIN DEFINITION
// ====================================

function Plugin(option) {
    return this.each(function () {
        var $this = $(this)
        var data = $this.data('bs.scrollspy')
        var options = typeof option == 'object' && option

        if (!data) $this.data('bs.scrollspy', (data = new MultipleScrollSpy(this, options)))
        if (typeof option == 'string') data[option]()
    })
}

var old = $.fn.multipleScrollspy;

$.fn.multipleScrollspy = Plugin;
$.fn.multipleScrollspy.Constructor = MultipleScrollSpy;


    // MULTIPLE SCROLLSPY NO CONFLICT
    // =============================

    ($.fn.multipleScrollspy || {}).noConflict = function () {
        $.fn.multipleScrollspy = old
        return this
    }


// MULTIPLE SCROLLSPY DATA-API
// ===========================

$(window).on('load.bs.scrollspy.data-api', function () {
    $('[data-multiple-spy="scroll"]').each(function () {
        var $spy = $(this)
        Plugin.call($spy, $spy.data())
    })
})

}(jQuery);