mirror of https://github.com/twbs/bootstrap.git
				
				
				
			Refactor determining affix state into a separate expanded method
in order to handle multiple edge cases, specifically when the document height is dynamic. Always reposition an affix that is affixed to the bottom.
This commit is contained in:
		
							parent
							
								
									d3dea01a11
								
							
						
					
					
						commit
						8c0eb9b00e
					
				
							
								
								
									
										63
									
								
								js/affix.js
								
								
								
								
							
							
						
						
									
										63
									
								
								js/affix.js
								
								
								
								
							| 
						 | 
				
			
			@ -37,6 +37,35 @@
 | 
			
		|||
    target: window
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
 | 
			
		||||
    var scrollTop     = this.$target.scrollTop()
 | 
			
		||||
    var position      = this.$element.offset()
 | 
			
		||||
    var targetHeight  = this.$target.height()
 | 
			
		||||
 | 
			
		||||
    if (offsetTop != null && this.affixed == 'top') return scrollTop >= offsetTop ? false : 'top'
 | 
			
		||||
    if (this.affixed == 'bottom') {
 | 
			
		||||
      // Can be affixed to the top, use the unpin value
 | 
			
		||||
      if (offsetTop != null) {
 | 
			
		||||
        return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
 | 
			
		||||
      // Can only ever be pinned or affixed to the bottom, ignore unpin value
 | 
			
		||||
      } else {
 | 
			
		||||
        return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      var initializing   = this.affixed == null
 | 
			
		||||
      var colliderTop    = initializing ? scrollTop : position.top
 | 
			
		||||
      var colliderHeight = initializing ? targetHeight : height
 | 
			
		||||
 | 
			
		||||
      if (offsetTop != null && colliderTop <= offsetTop) {
 | 
			
		||||
        return 'top'
 | 
			
		||||
      } else if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) {
 | 
			
		||||
        return 'bottom'
 | 
			
		||||
      } else {
 | 
			
		||||
        return false
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Affix.prototype.getPinnedOffset = function () {
 | 
			
		||||
    if (this.pinnedOffset) return this.pinnedOffset
 | 
			
		||||
    this.$element.removeClass(Affix.RESET).addClass('affix')
 | 
			
		||||
| 
						 | 
				
			
			@ -53,8 +82,7 @@
 | 
			
		|||
    if (!this.$element.is(':visible')) return
 | 
			
		||||
 | 
			
		||||
    var scrollHeight = $(document).height()
 | 
			
		||||
    var scrollTop    = this.$target.scrollTop()
 | 
			
		||||
    var position     = this.$element.offset()
 | 
			
		||||
    var height       = this.$element.height()
 | 
			
		||||
    var offset       = this.options.offset
 | 
			
		||||
    var offsetTop    = offset.top
 | 
			
		||||
    var offsetBottom = offset.bottom
 | 
			
		||||
| 
						 | 
				
			
			@ -63,31 +91,30 @@
 | 
			
		|||
    if (typeof offsetTop == 'function')    offsetTop    = offset.top(this.$element)
 | 
			
		||||
    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
 | 
			
		||||
 | 
			
		||||
    var affix = this.unpin   != null && (scrollTop + this.unpin <= position.top) ? false :
 | 
			
		||||
                offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' :
 | 
			
		||||
                offsetTop    != null && (scrollTop <= offsetTop) ? 'top' : false
 | 
			
		||||
    var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
 | 
			
		||||
 | 
			
		||||
    if (this.affixed === affix) return
 | 
			
		||||
    if (this.unpin != null) this.$element.css('top', '')
 | 
			
		||||
    if (this.affixed != affix) {
 | 
			
		||||
      if (this.unpin != null) this.$element.css('top', '')
 | 
			
		||||
 | 
			
		||||
    var affixType = 'affix' + (affix ? '-' + affix : '')
 | 
			
		||||
    var e         = $.Event(affixType + '.bs.affix')
 | 
			
		||||
      var affixType = 'affix' + (affix ? '-' + affix : '')
 | 
			
		||||
      var e         = $.Event(affixType + '.bs.affix')
 | 
			
		||||
 | 
			
		||||
    this.$element.trigger(e)
 | 
			
		||||
      this.$element.trigger(e)
 | 
			
		||||
 | 
			
		||||
    if (e.isDefaultPrevented()) return
 | 
			
		||||
      if (e.isDefaultPrevented()) return
 | 
			
		||||
 | 
			
		||||
    this.affixed = affix
 | 
			
		||||
    this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
 | 
			
		||||
      this.affixed = affix
 | 
			
		||||
      this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
 | 
			
		||||
 | 
			
		||||
    this.$element
 | 
			
		||||
      .removeClass(Affix.RESET)
 | 
			
		||||
      .addClass(affixType)
 | 
			
		||||
      .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
 | 
			
		||||
      this.$element
 | 
			
		||||
        .removeClass(Affix.RESET)
 | 
			
		||||
        .addClass(affixType)
 | 
			
		||||
        .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (affix == 'bottom') {
 | 
			
		||||
      this.$element.offset({
 | 
			
		||||
        top: scrollHeight - this.$element.height() - offsetBottom
 | 
			
		||||
        top: scrollHeight - height - offsetBottom
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue