首页 > 代码库 > scrollspy.js--bug

scrollspy.js--bug

/**
* 20140505 14.33 ycx
* scrollspy.js中存在的bug!!!---为什么ui.tabs必须在scrollspy.js中的window.onload之前执行,也就是必须在scrollspy初始化之前执行
* 1 scrollspy中的process函数中的scrollTop数值在tabs组件之后的都存在计算错误,是因为scrollspy初始化后,已经计算好整个页面的scrollTop等数组(offsets),而这时候ui.tabs进行初始化,
* 就会把tab页的其他暂时不显示出来的内容都隐藏起来,就会导致整个页面的scrollTop等方面的数值改变了,所以在tab之后的组件都会在scrollspy中存在偏差!!
* 针对这种情况,临时的解决方法是:
* 方法一: 将ui.tabs()在scrollspy初始化之前执行--如将ui.tabs()放到document.ready回调函数中执行(因为scrollspy是在window.onload回调函数执行的)
* 方法二: 将scrollspy初始化的函数拿出来,在ui.tabs()执行之后再开始初始化。
*
* 2 也就是说,如果其他组件或者js脚本会改变页面的scrollTop等方面的内容,那么估计都要采用上述两种方法来解决。
*/

 

1 ui.js---是我自己写的组件库

2 scrollspy.js可在bootstrap官网下载单独的源文件

scrollspy.js代码,具体如下所示:

  1 /* ========================================================================
  2  * Bootstrap: scrollspy.js v3.0.3
  3  * http://getbootstrap.com/javascript/#scrollspy
  4  * ========================================================================
  5  * Copyright 2013 Twitter, Inc.
  6  *
  7  * Licensed under the Apache License, Version 2.0 (the "License");
  8  * you may not use this file except in compliance with the License.
  9  * You may obtain a copy of the License at
 10  *
 11  * http://www.apache.org/licenses/LICENSE-2.0
 12  *
 13  * Unless required by applicable law or agreed to in writing, software
 14  * distributed under the License is distributed on an "AS IS" BASIS,
 15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 16  * See the License for the specific language governing permissions and
 17  * limitations under the License.
 18  * ======================================================================== */
 19 + function($) {"use strict";
 20 
 21     // SCROLLSPY CLASS DEFINITION
 22     // ==========================
 23 
 24     function ScrollSpy(element, options) {
 25         var href
 26         var process = $.proxy(this.process, this)
 27 
 28         this.$element = $(element).is(‘body‘) ? $(window) : $(element)
 29         this.$body = $(‘body‘)
 30         this.$scrollElement = this.$element.on(‘scroll.bs.scroll-spy.data-api‘, process)
 31         //console.log(this.$scrollElement);
 32         this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
 33         this.selector = (this.options.target || (( href = http://www.mamicode.com/$(element).attr(‘href‘)) && href.replace(/.*(?=#[^\s]+$)/, ‘‘))//strip for ie7
 34         || ‘‘) + ‘ .nav li > a‘
 35         //console.log(this.selector);
 36         this.offsets = $([])
 37         this.targets = $([])
 38         this.activeTarget = null
 39 
 40         this.refresh()
 41         this.process()
 42     }
 43 
 44 
 45     ScrollSpy.DEFAULTS = {
 46         offset : 10
 47     }
 48 
 49     ScrollSpy.prototype.refresh = function() {
 50         var offsetMethod = this.$element[0] == window ? ‘offset‘ : ‘position‘
 51         //console.log(offsetMethod,11);
 52 
 53         this.offsets = $([])
 54         this.targets = $([])
 55 
 56         var self = this
 57         var $targets = this.$body.find(this.selector).map(function() {
 58             var $el = $(this)
 59             var href = http://www.mamicode.com/$el.data(‘target‘) || $el.attr(‘href‘)
 60             var $href = http://www.mamicode.com/^#/w/.test(href) && $(href)
 61             //console.log($el,"--",href,"--",$href);
 62             console.log($href[offsetMethod]().top, "-------", $href[0].offsetTop, $href[0].id);
 63             //console.log($href,$href["offset"]().top,"-----------");
 64 
 65             return ($href && $href.length && [[$href[offsetMethod]().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href]]) || null
 66         }).sort(function(a, b) {
 67             return a[0] - b[0]
 68         }).each(function() {
 69             //console.log(this);
 70             self.offsets.push(this[0])
 71             self.targets.push(this[1])
 72         })
 73     }
 74 
 75     ScrollSpy.prototype.process = function() {
 76         //这里存在问题--scrollTop
 77         var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
 78         console.log("scrollTop--->>>" + scrollTop);
 79         var scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight
 80         var maxScroll = scrollHeight - this.$scrollElement.height()
 81         var offsets = this.offsets
 82         //console.log(offsets);
 83         var targets = this.targets
 84         var activeTarget = this.activeTarget
 85         var i
 86 
 87         if (scrollTop >= maxScroll) {
 88             return activeTarget != ( i = targets.last()[0]) && this.activate(i)
 89         }
 90 
 91         //console.log(scrollTop,offsets,)
 92 
 93         for ( i = offsets.length; i--; ) {
 94             //activeTarget != targets[i] && scrollTop >= offsets[i] && (!offsets[i + 1] || scrollTop <= offsets[i + 1]) && this.activate(targets[i])
 95 
 96             //activeTarget != targets[i] && scrollTop >= offsets[i] && (!offsets[i + 1] || scrollTop <= offsets[i + 1]) && this.activate(targets[i+1])
 97             activeTarget != targets[i] && scrollTop >= offsets[i] && (!offsets[i + 1] || scrollTop <= offsets[i + 1]) && this.activate(targets[i])
 98         }
 99     }
100 
101     ScrollSpy.prototype.activate = function(target) {
102         console.log("target===>>>", target);
103         this.activeTarget = target;
104 
105         $(this.selector).parents(‘.active‘).removeClass(‘active‘)
106 
107         var selector = this.selector + ‘[data-target="‘ + target + ‘"],‘ + this.selector + ‘[href="http://www.mamicode.com/‘ + target + ‘"]‘
108 
109         var active = $(selector).parents(‘li‘).addClass(‘active‘)
110 
111         if (active.parent(‘.dropdown-menu‘).length) {
112             active = active.closest(‘li.dropdown‘).addClass(‘active‘)
113         }
114 
115         active.trigger(‘activate.bs.scrollspy‘)
116     }
117     // SCROLLSPY PLUGIN DEFINITION
118     // ===========================
119 
120     var old = $.fn.scrollspy;
121 
122     $.fn.scrollspy = function(option) {
123         return this.each(function() {
124             var $this = $(this)
125             var data = http://www.mamicode.com/$this.data(‘bs.scrollspy‘)
126             var options = typeof option == ‘object‘ && option
127 
128             if (!data)
129                 $this.data(‘bs.scrollspy‘, ( data = http://www.mamicode.com/new ScrollSpy(this, options)))
130             if ( typeof option == ‘string‘)
131                 data[option]()
132         })
133     }
134 
135     $.fn.scrollspy.Constructor = ScrollSpy;
136 
137     // SCROLLSPY NO CONFLICT
138     // =====================
139 
140     $.fn.scrollspy.noConflict = function() {
141         $.fn.scrollspy = old;
142         return this;
143     }
144     // SCROLLSPY DATA-API
145     // ==================
146 
147     $(window).on(‘load‘, function() {
148         $(‘[data-spy="scroll"]‘).each(function() {
149             var $spy = $(this);
150             $spy.scrollspy($spy.data());
151         })
152     })
153 }(jQuery);