[ADD] doc: new documentation, with training tutorials, and new scaffolding
[odoo/odoo.git] / doc / _themes / odoodoc / static / bootstrap / js / scrollspy.js
1 /* ========================================================================
2  * Bootstrap: scrollspy.js v3.2.0
3  * http://getbootstrap.com/javascript/#scrollspy
4  * ========================================================================
5  * Copyright 2011-2014 Twitter, Inc.
6  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
7  * ======================================================================== */
8
9
10 +function ($) {
11   'use strict';
12
13   // SCROLLSPY CLASS DEFINITION
14   // ==========================
15
16   function ScrollSpy(element, options) {
17     var process  = $.proxy(this.process, this)
18
19     this.$body          = $('body')
20     this.$scrollElement = $(element).is('body') ? $(window) : $(element)
21     this.options        = $.extend({}, ScrollSpy.DEFAULTS, options)
22     this.selector       = (this.options.target || '') + ' .nav li > a'
23     this.offsets        = []
24     this.targets        = []
25     this.activeTarget   = null
26     this.scrollHeight   = 0
27
28     this.$scrollElement.on('scroll.bs.scrollspy', process)
29     this.refresh()
30     this.process()
31   }
32
33   ScrollSpy.VERSION  = '3.2.0'
34
35   ScrollSpy.DEFAULTS = {
36     offset: 10
37   }
38
39   ScrollSpy.prototype.getScrollHeight = function () {
40     return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
41   }
42
43   ScrollSpy.prototype.refresh = function () {
44     var offsetMethod = 'offset'
45     var offsetBase   = 0
46
47     if (!$.isWindow(this.$scrollElement[0])) {
48       offsetMethod = 'position'
49       offsetBase   = this.$scrollElement.scrollTop()
50     }
51
52     this.offsets = []
53     this.targets = []
54     this.scrollHeight = this.getScrollHeight()
55
56     var self     = this
57
58     this.$body
59       .find(this.selector)
60       .map(function () {
61         var $el   = $(this)
62         var href  = $el.data('target') || $el.attr('href')
63         var $href = /^#./.test(href) && $(href)
64
65         return ($href
66           && $href.length
67           && $href.is(':visible')
68           && [[$href[offsetMethod]().top + offsetBase, href]]) || null
69       })
70       .sort(function (a, b) { return a[0] - b[0] })
71       .each(function () {
72         self.offsets.push(this[0])
73         self.targets.push(this[1])
74       })
75   }
76
77   ScrollSpy.prototype.process = function () {
78     var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset
79     var scrollHeight = this.getScrollHeight()
80     var maxScroll    = this.options.offset + scrollHeight - this.$scrollElement.height()
81     var offsets      = this.offsets
82     var targets      = this.targets
83     var activeTarget = this.activeTarget
84     var i
85
86     if (this.scrollHeight != scrollHeight) {
87       this.refresh()
88     }
89
90     if (scrollTop >= maxScroll) {
91       return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
92     }
93
94     if (activeTarget && scrollTop <= offsets[0]) {
95       return activeTarget != (i = targets[0]) && this.activate(i)
96     }
97
98     for (i = offsets.length; i--;) {
99       activeTarget != targets[i]
100         && scrollTop >= offsets[i]
101         && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
102         && this.activate(targets[i])
103     }
104   }
105
106   ScrollSpy.prototype.activate = function (target) {
107     this.activeTarget = target
108
109     $(this.selector)
110       .parentsUntil(this.options.target, '.active')
111       .removeClass('active')
112
113     var selector = this.selector +
114         '[data-target="' + target + '"],' +
115         this.selector + '[href="' + target + '"]'
116
117     var active = $(selector)
118       .parents('li')
119       .addClass('active')
120
121     if (active.parent('.dropdown-menu').length) {
122       active = active
123         .closest('li.dropdown')
124         .addClass('active')
125     }
126
127     active.trigger('activate.bs.scrollspy')
128   }
129
130
131   // SCROLLSPY PLUGIN DEFINITION
132   // ===========================
133
134   function Plugin(option) {
135     return this.each(function () {
136       var $this   = $(this)
137       var data    = $this.data('bs.scrollspy')
138       var options = typeof option == 'object' && option
139
140       if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
141       if (typeof option == 'string') data[option]()
142     })
143   }
144
145   var old = $.fn.scrollspy
146
147   $.fn.scrollspy             = Plugin
148   $.fn.scrollspy.Constructor = ScrollSpy
149
150
151   // SCROLLSPY NO CONFLICT
152   // =====================
153
154   $.fn.scrollspy.noConflict = function () {
155     $.fn.scrollspy = old
156     return this
157   }
158
159
160   // SCROLLSPY DATA-API
161   // ==================
162
163   $(window).on('load.bs.scrollspy.data-api', function () {
164     $('[data-spy="scroll"]').each(function () {
165       var $spy = $(this)
166       Plugin.call($spy, $spy.data())
167     })
168   })
169
170 }(jQuery);