]> git.ipfire.org Git - thirdparty/bootstrap.git/commitdiff
Refactor determining affix state into a separate expanded method
authorCharles B Johnson <mail@cbjohnson.info>
Fri, 25 Apr 2014 03:15:38 +0000 (23:15 -0400)
committerCharles B Johnson <mail@cbjohnson.info>
Fri, 18 Jul 2014 14:45:59 +0000 (10:45 -0400)
  in order to handle multiple edge cases, specifically when the document
  height is dynamic.
Always reposition an affix that is affixed to the bottom.

js/affix.js

index 26b09db5685593ac1555e439644a4035f8174f3b..daebbffdd0a9f3c0aabf8088019e2374649eca99 100644 (file)
     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
     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
       })
     }
   }