3.0.0 -> 3.0.1
[bootswatch] / bower_components / bootstrap / js / affix.js
1 /* ========================================================================
2  * Bootstrap: affix.js v3.0.0
3  * http://getbootstrap.com/javascript/#affix
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
20
21 +function ($) { "use strict";
22
23   // AFFIX CLASS DEFINITION
24   // ======================
25
26   var Affix = function (element, options) {
27     this.options = $.extend({}, Affix.DEFAULTS, options)
28     this.$window = $(window)
29       .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
30       .on('click.bs.affix.data-api',  $.proxy(this.checkPositionWithEventLoop, this))
31
32     this.$element = $(element)
33     this.affixed  =
34     this.unpin    = null
35
36     this.checkPosition()
37   }
38
39   Affix.RESET = 'affix affix-top affix-bottom'
40
41   Affix.DEFAULTS = {
42     offset: 0
43   }
44
45   Affix.prototype.checkPositionWithEventLoop = function () {
46     setTimeout($.proxy(this.checkPosition, this), 1)
47   }
48
49   Affix.prototype.checkPosition = function () {
50     if (!this.$element.is(':visible')) return
51
52     var scrollHeight = $(document).height()
53     var scrollTop    = this.$window.scrollTop()
54     var position     = this.$element.offset()
55     var offset       = this.options.offset
56     var offsetTop    = offset.top
57     var offsetBottom = offset.bottom
58
59     if (typeof offset != 'object')         offsetBottom = offsetTop = offset
60     if (typeof offsetTop == 'function')    offsetTop    = offset.top()
61     if (typeof offsetBottom == 'function') offsetBottom = offset.bottom()
62
63     var affix = this.unpin   != null && (scrollTop + this.unpin <= position.top) ? false :
64                 offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' :
65                 offsetTop    != null && (scrollTop <= offsetTop) ? 'top' : false
66
67     if (this.affixed === affix) return
68     if (this.unpin) this.$element.css('top', '')
69
70     this.affixed = affix
71     this.unpin   = affix == 'bottom' ? position.top - scrollTop : null
72
73     this.$element.removeClass(Affix.RESET).addClass('affix' + (affix ? '-' + affix : ''))
74
75     if (affix == 'bottom') {
76       this.$element.offset({ top: document.body.offsetHeight - offsetBottom - this.$element.height() })
77     }
78   }
79
80
81   // AFFIX PLUGIN DEFINITION
82   // =======================
83
84   var old = $.fn.affix
85
86   $.fn.affix = function (option) {
87     return this.each(function () {
88       var $this   = $(this)
89       var data    = $this.data('bs.affix')
90       var options = typeof option == 'object' && option
91
92       if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
93       if (typeof option == 'string') data[option]()
94     })
95   }
96
97   $.fn.affix.Constructor = Affix
98
99
100   // AFFIX NO CONFLICT
101   // =================
102
103   $.fn.affix.noConflict = function () {
104     $.fn.affix = old
105     return this
106   }
107
108
109   // AFFIX DATA-API
110   // ==============
111
112   $(window).on('load', function () {
113     $('[data-spy="affix"]').each(function () {
114       var $spy = $(this)
115       var data = $spy.data()
116
117       data.offset = data.offset || {}
118
119       if (data.offsetBottom) data.offset.bottom = data.offsetBottom
120       if (data.offsetTop)    data.offset.top    = data.offsetTop
121
122       $spy.affix(data)
123     })
124   })
125
126 }(window.jQuery);