fomantic-ui 2.9.1-beta.16 → 2.9.1-beta.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (252) hide show
  1. package/.eslintrc.js +109 -0
  2. package/.github/workflows/ci.yml +13 -3
  3. package/dist/components/accordion.css +1 -1
  4. package/dist/components/accordion.js +571 -598
  5. package/dist/components/accordion.min.css +1 -1
  6. package/dist/components/accordion.min.js +1 -1
  7. package/dist/components/ad.css +1 -1
  8. package/dist/components/ad.min.css +1 -1
  9. package/dist/components/api.js +1164 -1186
  10. package/dist/components/api.min.js +1 -1
  11. package/dist/components/breadcrumb.css +1 -1
  12. package/dist/components/breadcrumb.min.css +1 -1
  13. package/dist/components/button.css +1 -1
  14. package/dist/components/button.min.css +1 -1
  15. package/dist/components/calendar.css +1 -1
  16. package/dist/components/calendar.js +1897 -1818
  17. package/dist/components/calendar.min.css +1 -1
  18. package/dist/components/calendar.min.js +1 -1
  19. package/dist/components/card.css +1 -1
  20. package/dist/components/card.min.css +1 -1
  21. package/dist/components/checkbox.css +1 -1
  22. package/dist/components/checkbox.js +844 -841
  23. package/dist/components/checkbox.min.css +1 -1
  24. package/dist/components/checkbox.min.js +1 -1
  25. package/dist/components/comment.css +1 -1
  26. package/dist/components/comment.min.css +1 -1
  27. package/dist/components/container.css +3 -1
  28. package/dist/components/container.min.css +2 -2
  29. package/dist/components/dimmer.css +1 -1
  30. package/dist/components/dimmer.js +710 -737
  31. package/dist/components/dimmer.min.css +1 -1
  32. package/dist/components/dimmer.min.js +1 -1
  33. package/dist/components/divider.css +1 -1
  34. package/dist/components/divider.min.css +1 -1
  35. package/dist/components/dropdown.css +11 -8
  36. package/dist/components/dropdown.js +4163 -4234
  37. package/dist/components/dropdown.min.css +2 -2
  38. package/dist/components/dropdown.min.js +2 -2
  39. package/dist/components/embed.css +1 -1
  40. package/dist/components/embed.js +653 -675
  41. package/dist/components/embed.min.css +1 -1
  42. package/dist/components/embed.min.js +1 -1
  43. package/dist/components/feed.css +1 -1
  44. package/dist/components/feed.min.css +1 -1
  45. package/dist/components/flag.css +1 -1
  46. package/dist/components/flag.min.css +1 -1
  47. package/dist/components/flyout.css +6 -3
  48. package/dist/components/flyout.js +1466 -1467
  49. package/dist/components/flyout.min.css +2 -2
  50. package/dist/components/flyout.min.js +1 -1
  51. package/dist/components/form.css +1 -1
  52. package/dist/components/form.js +1981 -2004
  53. package/dist/components/form.min.css +1 -1
  54. package/dist/components/form.min.js +1 -1
  55. package/dist/components/grid.css +1 -1
  56. package/dist/components/grid.min.css +1 -1
  57. package/dist/components/header.css +1 -1
  58. package/dist/components/header.min.css +1 -1
  59. package/dist/components/icon.css +1 -1
  60. package/dist/components/icon.min.css +1 -1
  61. package/dist/components/image.css +1 -1
  62. package/dist/components/image.min.css +1 -1
  63. package/dist/components/input.css +1 -1
  64. package/dist/components/input.min.css +1 -1
  65. package/dist/components/item.css +1 -1
  66. package/dist/components/item.min.css +1 -1
  67. package/dist/components/label.css +1 -1
  68. package/dist/components/label.min.css +1 -1
  69. package/dist/components/list.css +1 -1
  70. package/dist/components/list.min.css +1 -1
  71. package/dist/components/loader.css +1 -1
  72. package/dist/components/loader.min.css +1 -1
  73. package/dist/components/message.css +1 -1
  74. package/dist/components/message.min.css +1 -1
  75. package/dist/components/modal.css +7 -1
  76. package/dist/components/modal.js +1493 -1487
  77. package/dist/components/modal.min.css +2 -2
  78. package/dist/components/modal.min.js +1 -1
  79. package/dist/components/nag.css +1 -1
  80. package/dist/components/nag.js +520 -529
  81. package/dist/components/nag.min.css +1 -1
  82. package/dist/components/nag.min.js +1 -1
  83. package/dist/components/placeholder.css +1 -1
  84. package/dist/components/placeholder.min.css +1 -1
  85. package/dist/components/popup.css +1 -1
  86. package/dist/components/popup.js +1439 -1456
  87. package/dist/components/popup.min.css +1 -1
  88. package/dist/components/popup.min.js +1 -1
  89. package/dist/components/progress.css +1 -1
  90. package/dist/components/progress.js +971 -997
  91. package/dist/components/progress.min.css +1 -1
  92. package/dist/components/progress.min.js +1 -1
  93. package/dist/components/rail.css +1 -1
  94. package/dist/components/rail.min.css +1 -1
  95. package/dist/components/rating.css +1 -1
  96. package/dist/components/rating.js +508 -524
  97. package/dist/components/rating.min.css +1 -1
  98. package/dist/components/rating.min.js +1 -1
  99. package/dist/components/reset.css +1 -1
  100. package/dist/components/reset.min.css +1 -1
  101. package/dist/components/reveal.css +1 -1
  102. package/dist/components/reveal.min.css +1 -1
  103. package/dist/components/search.css +3 -1
  104. package/dist/components/search.js +1500 -1534
  105. package/dist/components/search.min.css +2 -2
  106. package/dist/components/search.min.js +1 -1
  107. package/dist/components/segment.css +3 -1
  108. package/dist/components/segment.min.css +2 -2
  109. package/dist/components/shape.css +1 -1
  110. package/dist/components/shape.js +794 -809
  111. package/dist/components/shape.min.css +1 -1
  112. package/dist/components/shape.min.js +1 -1
  113. package/dist/components/sidebar.css +3 -1
  114. package/dist/components/sidebar.js +1079 -1104
  115. package/dist/components/sidebar.min.css +2 -2
  116. package/dist/components/sidebar.min.js +1 -1
  117. package/dist/components/site.css +1 -1
  118. package/dist/components/site.js +457 -472
  119. package/dist/components/site.min.css +1 -1
  120. package/dist/components/site.min.js +1 -1
  121. package/dist/components/slider.js +1289 -1311
  122. package/dist/components/slider.min.js +1 -1
  123. package/dist/components/state.js +641 -657
  124. package/dist/components/state.min.js +1 -1
  125. package/dist/components/statistic.css +1 -1
  126. package/dist/components/statistic.min.css +1 -1
  127. package/dist/components/step.css +1 -1
  128. package/dist/components/step.min.css +1 -1
  129. package/dist/components/sticky.css +1 -1
  130. package/dist/components/sticky.js +859 -903
  131. package/dist/components/sticky.min.css +1 -1
  132. package/dist/components/sticky.min.js +1 -1
  133. package/dist/components/tab.css +1 -1
  134. package/dist/components/tab.js +923 -963
  135. package/dist/components/tab.min.css +1 -1
  136. package/dist/components/tab.min.js +1 -1
  137. package/dist/components/table.css +5 -1
  138. package/dist/components/table.min.css +2 -2
  139. package/dist/components/text.css +1 -1
  140. package/dist/components/text.min.css +1 -1
  141. package/dist/components/toast.css +1 -1
  142. package/dist/components/toast.js +889 -891
  143. package/dist/components/toast.min.css +1 -1
  144. package/dist/components/toast.min.js +1 -1
  145. package/dist/components/transition.css +1 -1
  146. package/dist/components/transition.js +1043 -1077
  147. package/dist/components/transition.min.css +1 -1
  148. package/dist/components/transition.min.js +1 -1
  149. package/dist/components/visibility.js +1222 -1244
  150. package/dist/components/visibility.min.js +1 -1
  151. package/dist/semantic.css +84 -60
  152. package/dist/semantic.js +29033 -29475
  153. package/dist/semantic.min.css +2 -2
  154. package/dist/semantic.min.js +2 -2
  155. package/examples/assets/show-examples.js +13 -13
  156. package/gulpfile.js +9 -10
  157. package/package.json +5 -2
  158. package/scripts/nightly-version.js +81 -75
  159. package/src/definitions/behaviors/api.js +1163 -1185
  160. package/src/definitions/behaviors/form.js +1980 -2003
  161. package/src/definitions/behaviors/state.js +647 -663
  162. package/src/definitions/behaviors/visibility.js +1221 -1243
  163. package/src/definitions/collections/table.less +2 -0
  164. package/src/definitions/elements/container.less +1 -0
  165. package/src/definitions/elements/segment.less +1 -0
  166. package/src/definitions/globals/site.js +456 -471
  167. package/src/definitions/modules/accordion.js +570 -597
  168. package/src/definitions/modules/calendar.js +1896 -1817
  169. package/src/definitions/modules/checkbox.js +849 -846
  170. package/src/definitions/modules/dimmer.js +709 -736
  171. package/src/definitions/modules/dropdown.js +4162 -4233
  172. package/src/definitions/modules/dropdown.less +5 -8
  173. package/src/definitions/modules/embed.js +652 -674
  174. package/src/definitions/modules/flyout.js +1465 -1466
  175. package/src/definitions/modules/flyout.less +15 -12
  176. package/src/definitions/modules/modal.js +1492 -1486
  177. package/src/definitions/modules/modal.less +3 -0
  178. package/src/definitions/modules/nag.js +519 -528
  179. package/src/definitions/modules/popup.js +1438 -1455
  180. package/src/definitions/modules/progress.js +970 -996
  181. package/src/definitions/modules/rating.js +507 -523
  182. package/src/definitions/modules/search.js +1499 -1533
  183. package/src/definitions/modules/search.less +1 -0
  184. package/src/definitions/modules/shape.js +801 -816
  185. package/src/definitions/modules/sidebar.js +1078 -1103
  186. package/src/definitions/modules/sidebar.less +1 -0
  187. package/src/definitions/modules/slider.js +1288 -1310
  188. package/src/definitions/modules/sticky.js +875 -919
  189. package/src/definitions/modules/tab.js +922 -962
  190. package/src/definitions/modules/toast.js +888 -890
  191. package/src/definitions/modules/transition.js +1048 -1082
  192. package/src/themes/default/elements/container.variables +0 -7
  193. package/src/themes/default/elements/segment.variables +0 -7
  194. package/src/themes/default/globals/site.variables +7 -0
  195. package/src/themes/default/globals/variation.variables +1 -0
  196. package/tasks/admin/components/create.js +274 -276
  197. package/tasks/admin/components/init.js +123 -130
  198. package/tasks/admin/components/update.js +149 -157
  199. package/tasks/admin/distributions/create.js +184 -187
  200. package/tasks/admin/distributions/init.js +123 -130
  201. package/tasks/admin/distributions/update.js +145 -152
  202. package/tasks/admin/publish.js +5 -7
  203. package/tasks/admin/register.js +36 -38
  204. package/tasks/admin/release.js +8 -10
  205. package/tasks/build/assets.js +42 -39
  206. package/tasks/build/css.js +225 -216
  207. package/tasks/build/javascript.js +118 -113
  208. package/tasks/build.js +10 -10
  209. package/tasks/check-install.js +14 -16
  210. package/tasks/clean.js +5 -5
  211. package/tasks/collections/admin.js +34 -36
  212. package/tasks/collections/build.js +18 -20
  213. package/tasks/collections/docs.js +9 -11
  214. package/tasks/collections/install.js +9 -11
  215. package/tasks/collections/rtl.js +9 -11
  216. package/tasks/collections/various.js +8 -10
  217. package/tasks/config/admin/github.js +17 -17
  218. package/tasks/config/admin/oauth.example.js +4 -4
  219. package/tasks/config/admin/release.js +98 -98
  220. package/tasks/config/admin/templates/component-package.js +9 -10
  221. package/tasks/config/admin/templates/css-package.js +18 -20
  222. package/tasks/config/admin/templates/less-package.js +11 -13
  223. package/tasks/config/defaults.js +116 -116
  224. package/tasks/config/docs.js +23 -23
  225. package/tasks/config/npm/gulpfile.js +8 -9
  226. package/tasks/config/project/config.js +127 -134
  227. package/tasks/config/project/install.js +715 -713
  228. package/tasks/config/project/release.js +32 -38
  229. package/tasks/config/tasks.js +163 -164
  230. package/tasks/config/user.js +23 -29
  231. package/tasks/docs/build.js +97 -95
  232. package/tasks/docs/metadata.js +90 -96
  233. package/tasks/docs/serve.js +80 -81
  234. package/tasks/install.js +370 -378
  235. package/tasks/rtl/build.js +2 -2
  236. package/tasks/rtl/watch.js +2 -2
  237. package/tasks/version.js +4 -4
  238. package/tasks/watch.js +28 -30
  239. package/test/meteor/assets.js +10 -13
  240. package/test/meteor/fonts.js +12 -13
  241. package/test/modules/accordion.spec.js +6 -8
  242. package/test/modules/checkbox.spec.js +5 -7
  243. package/test/modules/dropdown.spec.js +5 -7
  244. package/test/modules/modal.spec.js +6 -8
  245. package/test/modules/module.spec.js +158 -178
  246. package/test/modules/popup.spec.js +5 -7
  247. package/test/modules/search.spec.js +5 -7
  248. package/test/modules/shape.spec.js +5 -7
  249. package/test/modules/sidebar.spec.js +5 -7
  250. package/test/modules/tab.spec.js +6 -8
  251. package/test/modules/transition.spec.js +5 -7
  252. package/test/modules/video.spec.js +5 -7
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * # Fomantic-UI 2.9.1-beta.16+7071e59 - Sticky
2
+ * # Fomantic-UI 2.9.1-beta.18+935e235 - Sticky
3
3
  * https://github.com/fomantic/Fomantic-UI/
4
4
  *
5
5
  *
@@ -8,962 +8,918 @@
8
8
  *
9
9
  */
10
10
 
11
- ;(function ($, window, document, undefined) {
11
+ (function ($, window, document, undefined) {
12
+ 'use strict';
12
13
 
13
- 'use strict';
14
+ function isFunction(obj) {
15
+ return typeof obj === 'function' && typeof obj.nodeType !== 'number';
16
+ }
14
17
 
15
- function isFunction(obj) {
16
- return typeof obj === "function" && typeof obj.nodeType !== "number";
17
- }
18
+ window = (typeof window != 'undefined' && window.Math == Math)
19
+ ? window
20
+ : (typeof self != 'undefined' && self.Math == Math)
21
+ ? self
22
+ : Function('return this')();
18
23
 
19
- window = (typeof window != 'undefined' && window.Math == Math)
20
- ? window
21
- : (typeof self != 'undefined' && self.Math == Math)
22
- ? self
23
- : Function('return this')()
24
- ;
24
+ $.fn.sticky = function (parameters) {
25
+ var
26
+ $allModules = $(this),
27
+ $document = $(document),
28
+ moduleSelector = $allModules.selector || '',
25
29
 
26
- $.fn.sticky = function(parameters) {
27
- var
28
- $allModules = $(this),
29
- $document = $(document),
30
- moduleSelector = $allModules.selector || '',
30
+ time = new Date().getTime(),
31
+ performance = [],
31
32
 
32
- time = new Date().getTime(),
33
- performance = [],
33
+ query = arguments[0],
34
+ methodInvoked = (typeof query == 'string'),
35
+ queryArguments = [].slice.call(arguments, 1),
36
+ returnedValue
37
+ ;
34
38
 
35
- query = arguments[0],
36
- methodInvoked = (typeof query == 'string'),
37
- queryArguments = [].slice.call(arguments, 1),
38
- returnedValue
39
- ;
39
+ $allModules.each(function () {
40
+ var
41
+ settings = ($.isPlainObject(parameters))
42
+ ? $.extend(true, {}, $.fn.sticky.settings, parameters)
43
+ : $.extend({}, $.fn.sticky.settings),
44
+
45
+ className = settings.className,
46
+ namespace = settings.namespace,
47
+ error = settings.error,
48
+
49
+ eventNamespace = '.' + namespace,
50
+ moduleNamespace = 'module-' + namespace,
51
+
52
+ $module = $(this),
53
+ $window = $(window),
54
+ $scroll = [window, document].indexOf(settings.scrollContext) < 0 ? $document.find(settings.scrollContext) : $(settings.scrollContext),
55
+ $container,
56
+ $context,
57
+
58
+ instance = $module.data(moduleNamespace),
59
+
60
+ requestAnimationFrame = window.requestAnimationFrame
61
+ || window.mozRequestAnimationFrame
62
+ || window.webkitRequestAnimationFrame
63
+ || window.msRequestAnimationFrame
64
+ || function (callback) {
65
+ setTimeout(callback, 0);
66
+ },
67
+
68
+ element = this,
69
+
70
+ documentObserver,
71
+ observer,
72
+ module
73
+ ;
40
74
 
41
- $allModules
42
- .each(function() {
43
- var
44
- settings = ( $.isPlainObject(parameters) )
45
- ? $.extend(true, {}, $.fn.sticky.settings, parameters)
46
- : $.extend({}, $.fn.sticky.settings),
75
+ module = {
47
76
 
48
- className = settings.className,
49
- namespace = settings.namespace,
50
- error = settings.error,
77
+ initialize: function () {
78
+ module.determineContainer();
79
+ module.determineContext();
80
+ module.verbose('Initializing sticky', settings, $container);
51
81
 
52
- eventNamespace = '.' + namespace,
53
- moduleNamespace = 'module-' + namespace,
82
+ module.save.positions();
83
+ module.checkErrors();
84
+ module.bind.events();
54
85
 
55
- $module = $(this),
56
- $window = $(window),
57
- $scroll = [window,document].indexOf(settings.scrollContext) < 0 ? $document.find(settings.scrollContext) : $(settings.scrollContext),
58
- $container,
59
- $context,
86
+ if (settings.observeChanges) {
87
+ module.observeChanges();
88
+ }
89
+ module.instantiate();
90
+ },
60
91
 
61
- instance = $module.data(moduleNamespace),
92
+ instantiate: function () {
93
+ module.verbose('Storing instance of module', module);
94
+ instance = module;
95
+ $module
96
+ .data(moduleNamespace, module)
97
+ ;
98
+ },
62
99
 
63
- requestAnimationFrame = window.requestAnimationFrame
64
- || window.mozRequestAnimationFrame
65
- || window.webkitRequestAnimationFrame
66
- || window.msRequestAnimationFrame
67
- || function(callback) { setTimeout(callback, 0); },
100
+ destroy: function () {
101
+ module.verbose('Destroying previous instance');
102
+ module.reset();
103
+ if (documentObserver) {
104
+ documentObserver.disconnect();
105
+ }
106
+ if (observer) {
107
+ observer.disconnect();
108
+ }
109
+ $window
110
+ .off('load' + eventNamespace, module.event.load)
111
+ .off('resize' + eventNamespace, module.event.resize)
112
+ ;
113
+ $scroll
114
+ .off('scrollchange' + eventNamespace, module.event.scrollchange)
115
+ ;
116
+ $module.removeData(moduleNamespace);
117
+ },
68
118
 
69
- element = this,
119
+ observeChanges: function () {
120
+ if ('MutationObserver' in window) {
121
+ documentObserver = new MutationObserver(module.event.documentChanged);
122
+ observer = new MutationObserver(module.event.changed);
123
+ documentObserver.observe(document, {
124
+ childList: true,
125
+ subtree: true,
126
+ });
127
+ observer.observe(element, {
128
+ childList: true,
129
+ subtree: true,
130
+ });
131
+ observer.observe($context[0], {
132
+ childList: true,
133
+ subtree: true,
134
+ });
135
+ module.debug('Setting up mutation observer', observer);
136
+ }
137
+ },
70
138
 
71
- documentObserver,
72
- observer,
73
- module
74
- ;
139
+ determineContainer: function () {
140
+ if (settings.container) {
141
+ $container = [window, document].indexOf(settings.container) < 0 ? $document.find(settings.container) : $(settings.container);
142
+ } else {
143
+ $container = $module.offsetParent();
144
+ }
145
+ },
75
146
 
76
- module = {
147
+ determineContext: function () {
148
+ if (settings.context) {
149
+ $context = [window, document].indexOf(settings.context) < 0 ? $document.find(settings.context) : $(settings.context);
150
+ } else {
151
+ $context = $container;
152
+ }
153
+ if ($context.length === 0) {
154
+ module.error(error.invalidContext, settings.context, $module);
155
+ }
156
+ },
77
157
 
78
- initialize: function() {
158
+ checkErrors: function () {
159
+ if (module.is.hidden()) {
160
+ module.error(error.visible, $module);
161
+ }
162
+ if (module.cache.element.height > module.cache.context.height) {
163
+ module.reset();
164
+ module.error(error.elementSize, $module);
165
+ }
166
+ },
79
167
 
80
- module.determineContainer();
81
- module.determineContext();
82
- module.verbose('Initializing sticky', settings, $container);
168
+ bind: {
169
+ events: function () {
170
+ $window
171
+ .on('load' + eventNamespace, module.event.load)
172
+ .on('resize' + eventNamespace, module.event.resize)
173
+ ;
174
+ // pub/sub pattern
175
+ $scroll
176
+ .off('scroll' + eventNamespace)
177
+ .on('scroll' + eventNamespace, module.event.scroll)
178
+ .on('scrollchange' + eventNamespace, module.event.scrollchange)
179
+ ;
180
+ },
181
+ },
83
182
 
84
- module.save.positions();
85
- module.checkErrors();
86
- module.bind.events();
183
+ event: {
184
+ changed: function (mutations) {
185
+ clearTimeout(module.timer);
186
+ module.timer = setTimeout(function () {
187
+ module.verbose('DOM tree modified, updating sticky menu', mutations);
188
+ module.refresh();
189
+ }, 100);
190
+ },
191
+ documentChanged: function (mutations) {
192
+ [].forEach.call(mutations, function (mutation) {
193
+ if (mutation.removedNodes) {
194
+ [].forEach.call(mutation.removedNodes, function (node) {
195
+ if (node == element || $(node).find(element).length > 0) {
196
+ module.debug('Element removed from DOM, tearing down events');
197
+ module.destroy();
198
+ }
199
+ });
200
+ }
201
+ });
202
+ },
203
+ load: function () {
204
+ module.verbose('Page contents finished loading');
205
+ requestAnimationFrame(module.refresh);
206
+ },
207
+ resize: function () {
208
+ module.verbose('Window resized');
209
+ requestAnimationFrame(module.refresh);
210
+ },
211
+ scroll: function () {
212
+ requestAnimationFrame(function () {
213
+ $scroll.triggerHandler('scrollchange' + eventNamespace, $scroll.scrollTop());
214
+ });
215
+ },
216
+ scrollchange: function (event, scrollPosition) {
217
+ module.stick(scrollPosition);
218
+ settings.onScroll.call(element);
219
+ },
220
+ },
87
221
 
88
- if(settings.observeChanges) {
89
- module.observeChanges();
90
- }
91
- module.instantiate();
92
- },
222
+ refresh: function (hardRefresh) {
223
+ module.reset();
224
+ if (!settings.context) {
225
+ module.determineContext();
226
+ }
227
+ if (hardRefresh) {
228
+ module.determineContainer();
229
+ }
230
+ module.save.positions();
231
+ module.stick();
232
+ settings.onReposition.call(element);
233
+ },
93
234
 
94
- instantiate: function() {
95
- module.verbose('Storing instance of module', module);
96
- instance = module;
97
- $module
98
- .data(moduleNamespace, module)
99
- ;
100
- },
235
+ supports: {
236
+ sticky: function () {
237
+ var
238
+ $element = $('<div/>')
239
+ ;
240
+ $element.addClass(className.supported);
101
241
 
102
- destroy: function() {
103
- module.verbose('Destroying previous instance');
104
- module.reset();
105
- if(documentObserver) {
106
- documentObserver.disconnect();
107
- }
108
- if(observer) {
109
- observer.disconnect();
110
- }
111
- $window
112
- .off('load' + eventNamespace, module.event.load)
113
- .off('resize' + eventNamespace, module.event.resize)
114
- ;
115
- $scroll
116
- .off('scrollchange' + eventNamespace, module.event.scrollchange)
117
- ;
118
- $module.removeData(moduleNamespace);
119
- },
242
+ return ($element.css('position').match('sticky'));
243
+ },
244
+ },
120
245
 
121
- observeChanges: function() {
122
- if('MutationObserver' in window) {
123
- documentObserver = new MutationObserver(module.event.documentChanged);
124
- observer = new MutationObserver(module.event.changed);
125
- documentObserver.observe(document, {
126
- childList : true,
127
- subtree : true
128
- });
129
- observer.observe(element, {
130
- childList : true,
131
- subtree : true
132
- });
133
- observer.observe($context[0], {
134
- childList : true,
135
- subtree : true
136
- });
137
- module.debug('Setting up mutation observer', observer);
138
- }
139
- },
246
+ save: {
247
+ lastScroll: function (scroll) {
248
+ module.lastScroll = scroll;
249
+ },
250
+ elementScroll: function (scroll) {
251
+ module.elementScroll = scroll;
252
+ },
253
+ positions: function () {
254
+ var
255
+ scrollContext = {
256
+ height: $scroll.height(),
257
+ },
258
+ element = {
259
+ margin: {
260
+ top: parseInt($module.css('margin-top'), 10),
261
+ bottom: parseInt($module.css('margin-bottom'), 10),
262
+ },
263
+ offset: $module.offset(),
264
+ width: $module.outerWidth(),
265
+ height: $module.outerHeight(),
266
+ },
267
+ context = {
268
+ offset: $context.offset(),
269
+ height: $context.outerHeight(),
270
+ }
271
+ ;
272
+ if (!module.is.standardScroll()) {
273
+ module.debug('Non-standard scroll. Removing scroll offset from element offset');
274
+
275
+ scrollContext.top = $scroll.scrollTop();
276
+ scrollContext.left = $scroll.scrollLeft();
277
+
278
+ element.offset.top += scrollContext.top;
279
+ context.offset.top += scrollContext.top;
280
+ element.offset.left += scrollContext.left;
281
+ context.offset.left += scrollContext.left;
282
+ }
283
+ module.cache = {
284
+ fits: ((element.height + settings.offset) <= scrollContext.height),
285
+ sameHeight: (element.height == context.height),
286
+ scrollContext: {
287
+ height: scrollContext.height,
288
+ },
289
+ element: {
290
+ margin: element.margin,
291
+ top: element.offset.top - element.margin.top,
292
+ left: element.offset.left,
293
+ width: element.width,
294
+ height: element.height,
295
+ bottom: element.offset.top + element.height,
296
+ },
297
+ context: {
298
+ top: context.offset.top,
299
+ height: context.height,
300
+ bottom: context.offset.top + context.height,
301
+ },
302
+ };
303
+ module.set.containerSize();
304
+
305
+ module.stick();
306
+ module.debug('Caching element positions', module.cache);
307
+ },
308
+ },
140
309
 
141
- determineContainer: function() {
142
- if(settings.container) {
143
- $container = [window,document].indexOf(settings.container) < 0 ? $document.find(settings.container) : $(settings.container);
144
- }
145
- else {
146
- $container = $module.offsetParent();
147
- }
148
- },
310
+ get: {
311
+ direction: function (scroll) {
312
+ var
313
+ direction = 'down'
314
+ ;
315
+ scroll = scroll || $scroll.scrollTop();
316
+ if (module.lastScroll && module.lastScroll > scroll) {
317
+ direction = 'up';
318
+ }
319
+
320
+ return direction;
321
+ },
322
+ scrollChange: function (scroll) {
323
+ scroll = scroll || $scroll.scrollTop();
324
+
325
+ return (module.lastScroll)
326
+ ? (scroll - module.lastScroll)
327
+ : 0;
328
+ },
329
+ currentElementScroll: function () {
330
+ if (module.elementScroll) {
331
+ return module.elementScroll;
332
+ }
333
+
334
+ return (module.is.top())
335
+ ? Math.abs(parseInt($module.css('top'), 10)) || 0
336
+ : Math.abs(parseInt($module.css('bottom'), 10)) || 0;
337
+ },
338
+
339
+ elementScroll: function (scroll) {
340
+ scroll = scroll || $scroll.scrollTop();
341
+ var
342
+ element = module.cache.element,
343
+ scrollContext = module.cache.scrollContext,
344
+ delta = module.get.scrollChange(scroll),
345
+ maxScroll = (element.height - scrollContext.height + settings.offset),
346
+ elementScroll = module.get.currentElementScroll(),
347
+ possibleScroll = (elementScroll + delta)
348
+ ;
349
+ if (module.cache.fits || possibleScroll < 0) {
350
+ elementScroll = 0;
351
+ } else if (possibleScroll > maxScroll) {
352
+ elementScroll = maxScroll;
353
+ } else {
354
+ elementScroll = possibleScroll;
355
+ }
356
+
357
+ return elementScroll;
358
+ },
359
+ },
149
360
 
150
- determineContext: function() {
151
- if(settings.context) {
152
- $context = [window,document].indexOf(settings.context) < 0 ? $document.find(settings.context) : $(settings.context);
153
- }
154
- else {
155
- $context = $container;
156
- }
157
- if($context.length === 0) {
158
- module.error(error.invalidContext, settings.context, $module);
159
- }
160
- },
361
+ remove: {
362
+ lastScroll: function () {
363
+ delete module.lastScroll;
364
+ },
365
+ elementScroll: function () {
366
+ delete module.elementScroll;
367
+ },
368
+ minimumSize: function () {
369
+ $container
370
+ .css('min-height', '')
371
+ ;
372
+ },
373
+ offset: function () {
374
+ $module.css('margin-top', '');
375
+ },
376
+ },
161
377
 
162
- checkErrors: function() {
163
- if( module.is.hidden() ) {
164
- module.error(error.visible, $module);
165
- }
166
- if(module.cache.element.height > module.cache.context.height) {
167
- module.reset();
168
- module.error(error.elementSize, $module);
169
- }
170
- },
378
+ set: {
379
+ offset: function () {
380
+ module.verbose('Setting offset on element', settings.offset);
381
+ $module
382
+ .css('margin-top', settings.offset)
383
+ ;
384
+ },
385
+ containerSize: function () {
386
+ var
387
+ tagName = $container[0].tagName
388
+ ;
389
+ if (tagName === 'HTML' || tagName === 'body') {
390
+ // this can trigger for too many reasons
391
+ // module.error(error.container, tagName, $module);
392
+ module.determineContainer();
393
+ } else {
394
+ var tallestHeight = Math.max(module.cache.context.height, module.cache.element.height);
395
+ if (tallestHeight - $container.outerHeight() > settings.jitter) {
396
+ module.debug('Context is taller than container. Specifying exact height for container', module.cache.context.height);
397
+ $container.css({
398
+ height: tallestHeight,
399
+ });
400
+ } else {
401
+ $container.css({
402
+ height: '',
403
+ });
404
+ }
405
+ if (Math.abs($container.outerHeight() - module.cache.context.height) > settings.jitter) {
406
+ module.debug('Context has padding, specifying exact height for container', module.cache.context.height);
407
+ $container.css({
408
+ height: module.cache.context.height,
409
+ });
410
+ }
411
+ }
412
+ },
413
+ minimumSize: function () {
414
+ var
415
+ element = module.cache.element
416
+ ;
417
+ $container
418
+ .css('min-height', element.height)
419
+ ;
420
+ },
421
+ scroll: function (scroll) {
422
+ module.debug('Setting scroll on element', scroll);
423
+ if (module.elementScroll == scroll) {
424
+ return;
425
+ }
426
+ if (module.is.top()) {
427
+ $module
428
+ .css('bottom', '')
429
+ .css('top', (-scroll) + 'px')
430
+ ;
431
+ }
432
+ if (module.is.bottom()) {
433
+ $module
434
+ .css('top', '')
435
+ .css('bottom', scroll + 'px')
436
+ ;
437
+ }
438
+ },
439
+ size: function () {
440
+ if (module.cache.element.height !== 0 && module.cache.element.width !== 0) {
441
+ element.style.setProperty('width', module.cache.element.width + 'px', 'important');
442
+ element.style.setProperty('height', module.cache.element.height + 'px', 'important');
443
+ }
444
+ },
445
+ },
171
446
 
172
- bind: {
173
- events: function() {
174
- $window
175
- .on('load' + eventNamespace, module.event.load)
176
- .on('resize' + eventNamespace, module.event.resize)
177
- ;
178
- // pub/sub pattern
179
- $scroll
180
- .off('scroll' + eventNamespace)
181
- .on('scroll' + eventNamespace, module.event.scroll)
182
- .on('scrollchange' + eventNamespace, module.event.scrollchange)
183
- ;
184
- }
185
- },
447
+ is: {
448
+ standardScroll: function () {
449
+ return ($scroll[0] == window);
450
+ },
451
+ top: function () {
452
+ return $module.hasClass(className.top);
453
+ },
454
+ bottom: function () {
455
+ return $module.hasClass(className.bottom);
456
+ },
457
+ initialPosition: function () {
458
+ return (!module.is.fixed() && !module.is.bound());
459
+ },
460
+ hidden: function () {
461
+ return (!$module.is(':visible'));
462
+ },
463
+ bound: function () {
464
+ return $module.hasClass(className.bound);
465
+ },
466
+ fixed: function () {
467
+ return $module.hasClass(className.fixed);
468
+ },
469
+ },
186
470
 
187
- event: {
188
- changed: function(mutations) {
189
- clearTimeout(module.timer);
190
- module.timer = setTimeout(function() {
191
- module.verbose('DOM tree modified, updating sticky menu', mutations);
192
- module.refresh();
193
- }, 100);
194
- },
195
- documentChanged: function(mutations) {
196
- [].forEach.call(mutations, function(mutation) {
197
- if(mutation.removedNodes) {
198
- [].forEach.call(mutation.removedNodes, function(node) {
199
- if(node == element || $(node).find(element).length > 0) {
200
- module.debug('Element removed from DOM, tearing down events');
201
- module.destroy();
202
- }
203
- });
204
- }
205
- });
206
- },
207
- load: function() {
208
- module.verbose('Page contents finished loading');
209
- requestAnimationFrame(module.refresh);
210
- },
211
- resize: function() {
212
- module.verbose('Window resized');
213
- requestAnimationFrame(module.refresh);
214
- },
215
- scroll: function() {
216
- requestAnimationFrame(function() {
217
- $scroll.triggerHandler('scrollchange' + eventNamespace, $scroll.scrollTop() );
218
- });
219
- },
220
- scrollchange: function(event, scrollPosition) {
221
- module.stick(scrollPosition);
222
- settings.onScroll.call(element);
223
- }
224
- },
471
+ stick: function (scrollPosition) {
472
+ var
473
+ cachedPosition = scrollPosition || $scroll.scrollTop(),
474
+ cache = module.cache,
475
+ fits = cache.fits,
476
+ sameHeight = cache.sameHeight,
477
+ element = cache.element,
478
+ scrollContext = cache.scrollContext,
479
+ context = cache.context,
480
+ offset = (module.is.bottom() && settings.pushing)
481
+ ? settings.bottomOffset
482
+ : settings.offset,
483
+ scroll = {
484
+ top: cachedPosition + offset,
485
+ bottom: cachedPosition + offset + scrollContext.height,
486
+ },
487
+ elementScroll = (fits)
488
+ ? 0
489
+ : module.get.elementScroll(scroll.top),
490
+
491
+ // shorthand
492
+ doesntFit = !fits,
493
+ elementVisible = (element.height !== 0)
494
+ ;
495
+ if (elementVisible && !sameHeight) {
496
+ if (module.is.initialPosition()) {
497
+ if (scroll.top >= context.bottom) {
498
+ module.debug('Initial element position is bottom of container');
499
+ module.bindBottom();
500
+ } else if (scroll.top > element.top) {
501
+ if ((element.height + scroll.top - elementScroll) >= context.bottom && element.height < context.height) {
502
+ module.debug('Initial element position is bottom of container');
503
+ module.bindBottom();
504
+ } else {
505
+ module.debug('Initial element position is fixed');
506
+ module.fixTop();
507
+ }
508
+ }
509
+ } else if (module.is.fixed()) {
510
+ if (module.is.top()) {
511
+ if (scroll.top <= element.top) {
512
+ module.debug('Fixed element reached top of container');
513
+ module.setInitialPosition();
514
+ } else if ((element.height + scroll.top - elementScroll) >= context.bottom) {
515
+ module.debug('Fixed element reached bottom of container');
516
+ module.bindBottom();
517
+ } else if (doesntFit) { // scroll element if larger than screen
518
+ module.set.scroll(elementScroll);
519
+ module.save.lastScroll(scroll.top);
520
+ module.save.elementScroll(elementScroll);
521
+ }
522
+ } else if (module.is.bottom()) {
523
+ if ((scroll.bottom - element.height) <= element.top) { // top edge
524
+ module.debug('Bottom fixed rail has reached top of container');
525
+ module.setInitialPosition();
526
+ } else if (scroll.bottom >= context.bottom) { // bottom edge
527
+ module.debug('Bottom fixed rail has reached bottom of container');
528
+ module.bindBottom();
529
+ } else if (doesntFit) { // scroll element if larger than screen
530
+ module.set.scroll(elementScroll);
531
+ module.save.lastScroll(scroll.top);
532
+ module.save.elementScroll(elementScroll);
533
+ }
534
+ }
535
+ } else if (module.is.bottom()) {
536
+ if (scroll.top <= element.top) {
537
+ module.debug('Jumped from bottom fixed to top fixed, most likely used home/end button');
538
+ module.setInitialPosition();
539
+ } else {
540
+ if (settings.pushing) {
541
+ if (module.is.bound() && scroll.bottom <= context.bottom) {
542
+ module.debug('Fixing bottom attached element to bottom of browser.');
543
+ module.fixBottom();
544
+ }
545
+ } else {
546
+ if (module.is.bound() && (scroll.top <= context.bottom - element.height)) {
547
+ module.debug('Fixing bottom attached element to top of browser.');
548
+ module.fixTop();
549
+ }
550
+ }
551
+ }
552
+ }
553
+ }
554
+ },
225
555
 
226
- refresh: function(hardRefresh) {
227
- module.reset();
228
- if(!settings.context) {
229
- module.determineContext();
230
- }
231
- if(hardRefresh) {
232
- module.determineContainer();
233
- }
234
- module.save.positions();
235
- module.stick();
236
- settings.onReposition.call(element);
237
- },
556
+ bindTop: function () {
557
+ module.debug('Binding element to top of parent container');
558
+ module.remove.offset();
559
+ if (settings.setSize) {
560
+ module.set.size();
561
+ }
562
+ $module
563
+ .css({
564
+ left: '',
565
+ top: '',
566
+ marginBottom: '',
567
+ })
568
+ .removeClass(className.fixed)
569
+ .removeClass(className.bottom)
570
+ .addClass(className.bound)
571
+ .addClass(className.top)
572
+ ;
573
+ settings.onTop.call(element);
574
+ settings.onUnstick.call(element);
575
+ },
576
+ bindBottom: function () {
577
+ module.debug('Binding element to bottom of parent container');
578
+ module.remove.offset();
579
+ if (settings.setSize) {
580
+ module.set.size();
581
+ }
582
+ $module
583
+ .css({
584
+ left: '',
585
+ top: '',
586
+ })
587
+ .removeClass(className.fixed)
588
+ .removeClass(className.top)
589
+ .addClass(className.bound)
590
+ .addClass(className.bottom)
591
+ ;
592
+ settings.onBottom.call(element);
593
+ settings.onUnstick.call(element);
594
+ },
238
595
 
239
- supports: {
240
- sticky: function() {
241
- var
242
- $element = $('<div/>')
243
- ;
244
- $element.addClass(className.supported);
245
- return($element.css('position').match('sticky'));
246
- }
247
- },
596
+ setInitialPosition: function () {
597
+ module.debug('Returning to initial position');
598
+ module.unfix();
599
+ module.unbind();
600
+ },
248
601
 
249
- save: {
250
- lastScroll: function(scroll) {
251
- module.lastScroll = scroll;
252
- },
253
- elementScroll: function(scroll) {
254
- module.elementScroll = scroll;
255
- },
256
- positions: function() {
257
- var
258
- scrollContext = {
259
- height : $scroll.height()
260
- },
261
- element = {
262
- margin: {
263
- top : parseInt($module.css('margin-top'), 10),
264
- bottom : parseInt($module.css('margin-bottom'), 10),
265
- },
266
- offset : $module.offset(),
267
- width : $module.outerWidth(),
268
- height : $module.outerHeight()
269
- },
270
- context = {
271
- offset : $context.offset(),
272
- height : $context.outerHeight()
273
- }
274
- ;
275
- if( !module.is.standardScroll() ) {
276
- module.debug('Non-standard scroll. Removing scroll offset from element offset');
602
+ fixTop: function () {
603
+ module.debug('Fixing element to top of page');
604
+ if (settings.setSize) {
605
+ module.set.size();
606
+ }
607
+ module.set.minimumSize();
608
+ module.set.offset();
609
+ $module
610
+ .css({
611
+ left: module.cache.element.left,
612
+ bottom: '',
613
+ marginBottom: '',
614
+ })
615
+ .removeClass(className.bound)
616
+ .removeClass(className.bottom)
617
+ .addClass(className.fixed)
618
+ .addClass(className.top)
619
+ ;
620
+ settings.onStick.call(element);
621
+ },
277
622
 
278
- scrollContext.top = $scroll.scrollTop();
279
- scrollContext.left = $scroll.scrollLeft();
623
+ fixBottom: function () {
624
+ module.debug('Sticking element to bottom of page');
625
+ if (settings.setSize) {
626
+ module.set.size();
627
+ }
628
+ module.set.minimumSize();
629
+ module.set.offset();
630
+ $module
631
+ .css({
632
+ left: module.cache.element.left,
633
+ bottom: '',
634
+ marginBottom: '',
635
+ })
636
+ .removeClass(className.bound)
637
+ .removeClass(className.top)
638
+ .addClass(className.fixed)
639
+ .addClass(className.bottom)
640
+ ;
641
+ settings.onStick.call(element);
642
+ },
280
643
 
281
- element.offset.top += scrollContext.top;
282
- context.offset.top += scrollContext.top;
283
- element.offset.left += scrollContext.left;
284
- context.offset.left += scrollContext.left;
285
- }
286
- module.cache = {
287
- fits : ( (element.height + settings.offset) <= scrollContext.height),
288
- sameHeight : (element.height == context.height),
289
- scrollContext : {
290
- height : scrollContext.height
291
- },
292
- element: {
293
- margin : element.margin,
294
- top : element.offset.top - element.margin.top,
295
- left : element.offset.left,
296
- width : element.width,
297
- height : element.height,
298
- bottom : element.offset.top + element.height
299
- },
300
- context: {
301
- top : context.offset.top,
302
- height : context.height,
303
- bottom : context.offset.top + context.height
304
- }
305
- };
306
- module.set.containerSize();
644
+ unbind: function () {
645
+ if (module.is.bound()) {
646
+ module.debug('Removing container bound position on element');
647
+ module.remove.offset();
648
+ $module
649
+ .removeClass(className.bound)
650
+ .removeClass(className.top)
651
+ .removeClass(className.bottom)
652
+ ;
653
+ }
654
+ },
307
655
 
308
- module.stick();
309
- module.debug('Caching element positions', module.cache);
310
- }
311
- },
656
+ unfix: function () {
657
+ if (module.is.fixed()) {
658
+ module.debug('Removing fixed position on element');
659
+ module.remove.minimumSize();
660
+ module.remove.offset();
661
+ $module
662
+ .removeClass(className.fixed)
663
+ .removeClass(className.top)
664
+ .removeClass(className.bottom)
665
+ ;
666
+ settings.onUnstick.call(element);
667
+ }
668
+ },
312
669
 
313
- get: {
314
- direction: function(scroll) {
315
- var
316
- direction = 'down'
317
- ;
318
- scroll = scroll || $scroll.scrollTop();
319
- if(module.lastScroll && module.lastScroll > scroll) {
320
- direction = 'up';
321
- }
322
- return direction;
323
- },
324
- scrollChange: function(scroll) {
325
- scroll = scroll || $scroll.scrollTop();
326
- return (module.lastScroll)
327
- ? (scroll - module.lastScroll)
328
- : 0
329
- ;
330
- },
331
- currentElementScroll: function() {
332
- if(module.elementScroll) {
333
- return module.elementScroll;
334
- }
335
- return ( module.is.top() )
336
- ? Math.abs(parseInt($module.css('top'), 10)) || 0
337
- : Math.abs(parseInt($module.css('bottom'), 10)) || 0
338
- ;
339
- },
670
+ reset: function () {
671
+ module.debug('Resetting elements position');
672
+ module.unbind();
673
+ module.unfix();
674
+ module.resetCSS();
675
+ module.remove.offset();
676
+ module.remove.lastScroll();
677
+ },
340
678
 
341
- elementScroll: function(scroll) {
342
- scroll = scroll || $scroll.scrollTop();
343
- var
344
- element = module.cache.element,
345
- scrollContext = module.cache.scrollContext,
346
- delta = module.get.scrollChange(scroll),
347
- maxScroll = (element.height - scrollContext.height + settings.offset),
348
- elementScroll = module.get.currentElementScroll(),
349
- possibleScroll = (elementScroll + delta)
350
- ;
351
- if(module.cache.fits || possibleScroll < 0) {
352
- elementScroll = 0;
353
- }
354
- else if(possibleScroll > maxScroll ) {
355
- elementScroll = maxScroll;
356
- }
357
- else {
358
- elementScroll = possibleScroll;
359
- }
360
- return elementScroll;
361
- }
362
- },
679
+ resetCSS: function () {
680
+ $module
681
+ .css({
682
+ width: '',
683
+ height: '',
684
+ })
685
+ ;
686
+ $container
687
+ .css({
688
+ height: '',
689
+ })
690
+ ;
691
+ },
363
692
 
364
- remove: {
365
- lastScroll: function() {
366
- delete module.lastScroll;
367
- },
368
- elementScroll: function() {
369
- delete module.elementScroll;
370
- },
371
- minimumSize: function() {
372
- $container
373
- .css('min-height', '')
374
- ;
375
- },
376
- offset: function() {
377
- $module.css('margin-top', '');
378
- }
379
- },
693
+ setting: function (name, value) {
694
+ if ($.isPlainObject(name)) {
695
+ $.extend(true, settings, name);
696
+ } else if (value !== undefined) {
697
+ settings[name] = value;
698
+ } else {
699
+ return settings[name];
700
+ }
701
+ },
702
+ internal: function (name, value) {
703
+ if ($.isPlainObject(name)) {
704
+ $.extend(true, module, name);
705
+ } else if (value !== undefined) {
706
+ module[name] = value;
707
+ } else {
708
+ return module[name];
709
+ }
710
+ },
711
+ debug: function () {
712
+ if (!settings.silent && settings.debug) {
713
+ if (settings.performance) {
714
+ module.performance.log(arguments);
715
+ } else {
716
+ module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
717
+ module.debug.apply(console, arguments);
718
+ }
719
+ }
720
+ },
721
+ verbose: function () {
722
+ if (!settings.silent && settings.verbose && settings.debug) {
723
+ if (settings.performance) {
724
+ module.performance.log(arguments);
725
+ } else {
726
+ module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
727
+ module.verbose.apply(console, arguments);
728
+ }
729
+ }
730
+ },
731
+ error: function () {
732
+ if (!settings.silent) {
733
+ module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
734
+ module.error.apply(console, arguments);
735
+ }
736
+ },
737
+ performance: {
738
+ log: function (message) {
739
+ var
740
+ currentTime,
741
+ executionTime,
742
+ previousTime
743
+ ;
744
+ if (settings.performance) {
745
+ currentTime = new Date().getTime();
746
+ previousTime = time || currentTime;
747
+ executionTime = currentTime - previousTime;
748
+ time = currentTime;
749
+ performance.push({
750
+ Name: message[0],
751
+ Arguments: [].slice.call(message, 1) || '',
752
+ Element: element,
753
+ 'Execution Time': executionTime,
754
+ });
755
+ }
756
+ clearTimeout(module.performance.timer);
757
+ module.performance.timer = setTimeout(module.performance.display, 0);
758
+ },
759
+ display: function () {
760
+ var
761
+ title = settings.name + ':',
762
+ totalTime = 0
763
+ ;
764
+ time = false;
765
+ clearTimeout(module.performance.timer);
766
+ $.each(performance, function (index, data) {
767
+ totalTime += data['Execution Time'];
768
+ });
769
+ title += ' ' + totalTime + 'ms';
770
+ if (moduleSelector) {
771
+ title += ' \'' + moduleSelector + '\'';
772
+ }
773
+ if ((console.group !== undefined || console.table !== undefined) && performance.length > 0) {
774
+ console.groupCollapsed(title);
775
+ if (console.table) {
776
+ console.table(performance);
777
+ } else {
778
+ $.each(performance, function (index, data) {
779
+ console.log(data.Name + ': ' + data['Execution Time'] + 'ms');
780
+ });
781
+ }
782
+ console.groupEnd();
783
+ }
784
+ performance = [];
785
+ },
786
+ },
787
+ invoke: function (query, passedArguments, context) {
788
+ var
789
+ object = instance,
790
+ maxDepth,
791
+ found,
792
+ response
793
+ ;
794
+ passedArguments = passedArguments || queryArguments;
795
+ context = context || element;
796
+ if (typeof query == 'string' && object !== undefined) {
797
+ query = query.split(/[\. ]/);
798
+ maxDepth = query.length - 1;
799
+ $.each(query, function (depth, value) {
800
+ var camelCaseValue = (depth != maxDepth)
801
+ ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
802
+ : query
803
+ ;
804
+ if ($.isPlainObject(object[camelCaseValue]) && (depth != maxDepth)) {
805
+ object = object[camelCaseValue];
806
+ } else if (object[camelCaseValue] !== undefined) {
807
+ found = object[camelCaseValue];
808
+
809
+ return false;
810
+ } else if ($.isPlainObject(object[value]) && (depth != maxDepth)) {
811
+ object = object[value];
812
+ } else if (object[value] !== undefined) {
813
+ found = object[value];
814
+
815
+ return false;
816
+ } else {
817
+ return false;
818
+ }
819
+ });
820
+ }
821
+ if (isFunction(found)) {
822
+ response = found.apply(context, passedArguments);
823
+ } else if (found !== undefined) {
824
+ response = found;
825
+ }
826
+ if (Array.isArray(returnedValue)) {
827
+ returnedValue.push(response);
828
+ } else if (returnedValue !== undefined) {
829
+ returnedValue = [returnedValue, response];
830
+ } else if (response !== undefined) {
831
+ returnedValue = response;
832
+ }
833
+
834
+ return found;
835
+ },
836
+ };
380
837
 
381
- set: {
382
- offset: function() {
383
- module.verbose('Setting offset on element', settings.offset);
384
- $module
385
- .css('margin-top', settings.offset)
386
- ;
387
- },
388
- containerSize: function() {
389
- var
390
- tagName = $container[0].tagName
391
- ;
392
- if(tagName === 'HTML' || tagName === 'body') {
393
- // this can trigger for too many reasons
394
- //module.error(error.container, tagName, $module);
395
- module.determineContainer();
396
- }
397
- else {
398
- var tallestHeight = Math.max(module.cache.context.height, module.cache.element.height);
399
- if(tallestHeight - $container.outerHeight() > settings.jitter) {
400
- module.debug('Context is taller than container. Specifying exact height for container', module.cache.context.height);
401
- $container.css({
402
- height: tallestHeight,
403
- });
404
- }
405
- else {
406
- $container.css({
407
- height: '',
408
- });
409
- }
410
- if( Math.abs($container.outerHeight() - module.cache.context.height) > settings.jitter) {
411
- module.debug('Context has padding, specifying exact height for container', module.cache.context.height);
412
- $container.css({
413
- height: module.cache.context.height
414
- });
415
- }
416
- }
417
- },
418
- minimumSize: function() {
419
- var
420
- element = module.cache.element
421
- ;
422
- $container
423
- .css('min-height', element.height)
424
- ;
425
- },
426
- scroll: function(scroll) {
427
- module.debug('Setting scroll on element', scroll);
428
- if(module.elementScroll == scroll) {
429
- return;
430
- }
431
- if( module.is.top() ) {
432
- $module
433
- .css('bottom', '')
434
- .css('top', (-scroll) + 'px')
435
- ;
436
- }
437
- if( module.is.bottom() ) {
438
- $module
439
- .css('top', '')
440
- .css('bottom', scroll + 'px')
441
- ;
442
- }
443
- },
444
- size: function() {
445
- if(module.cache.element.height !== 0 && module.cache.element.width !== 0) {
446
- element.style.setProperty('width', module.cache.element.width + 'px', 'important');
447
- element.style.setProperty('height', module.cache.element.height + 'px', 'important');
838
+ if (methodInvoked) {
839
+ if (instance === undefined) {
840
+ module.initialize();
841
+ }
842
+ module.invoke(query);
843
+ } else {
844
+ if (instance !== undefined) {
845
+ instance.invoke('destroy');
846
+ }
847
+ module.initialize();
448
848
  }
449
- }
450
- },
849
+ });
451
850
 
452
- is: {
453
- standardScroll: function() {
454
- return ($scroll[0] == window);
455
- },
456
- top: function() {
457
- return $module.hasClass(className.top);
458
- },
459
- bottom: function() {
460
- return $module.hasClass(className.bottom);
461
- },
462
- initialPosition: function() {
463
- return (!module.is.fixed() && !module.is.bound());
464
- },
465
- hidden: function() {
466
- return (!$module.is(':visible'));
467
- },
468
- bound: function() {
469
- return $module.hasClass(className.bound);
470
- },
471
- fixed: function() {
472
- return $module.hasClass(className.fixed);
473
- }
474
- },
851
+ return (returnedValue !== undefined)
852
+ ? returnedValue
853
+ : this;
854
+ };
475
855
 
476
- stick: function(scrollPosition) {
477
- var
478
- cachedPosition = scrollPosition || $scroll.scrollTop(),
479
- cache = module.cache,
480
- fits = cache.fits,
481
- sameHeight = cache.sameHeight,
482
- element = cache.element,
483
- scrollContext = cache.scrollContext,
484
- context = cache.context,
485
- offset = (module.is.bottom() && settings.pushing)
486
- ? settings.bottomOffset
487
- : settings.offset,
488
- scroll = {
489
- top : cachedPosition + offset,
490
- bottom : cachedPosition + offset + scrollContext.height
491
- },
492
- elementScroll = (fits)
493
- ? 0
494
- : module.get.elementScroll(scroll.top),
495
-
496
- // shorthand
497
- doesntFit = !fits,
498
- elementVisible = (element.height !== 0)
499
- ;
500
- if(elementVisible && !sameHeight) {
501
-
502
- if( module.is.initialPosition() ) {
503
- if(scroll.top >= context.bottom) {
504
- module.debug('Initial element position is bottom of container');
505
- module.bindBottom();
506
- }
507
- else if(scroll.top > element.top) {
508
- if( (element.height + scroll.top - elementScroll) >= context.bottom && element.height < context.height) {
509
- module.debug('Initial element position is bottom of container');
510
- module.bindBottom();
511
- }
512
- else {
513
- module.debug('Initial element position is fixed');
514
- module.fixTop();
515
- }
516
- }
856
+ $.fn.sticky.settings = {
517
857
 
518
- }
519
- else if( module.is.fixed() ) {
858
+ name: 'Sticky',
859
+ namespace: 'sticky',
520
860
 
521
- // currently fixed top
522
- if( module.is.top() ) {
523
- if( scroll.top <= element.top ) {
524
- module.debug('Fixed element reached top of container');
525
- module.setInitialPosition();
526
- }
527
- else if( (element.height + scroll.top - elementScroll) >= context.bottom ) {
528
- module.debug('Fixed element reached bottom of container');
529
- module.bindBottom();
530
- }
531
- // scroll element if larger than screen
532
- else if(doesntFit) {
533
- module.set.scroll(elementScroll);
534
- module.save.lastScroll(scroll.top);
535
- module.save.elementScroll(elementScroll);
536
- }
537
- }
861
+ silent: false,
862
+ debug: false,
863
+ verbose: true,
864
+ performance: true,
538
865
 
539
- // currently fixed bottom
540
- else if(module.is.bottom() ) {
866
+ // whether to stick in the opposite direction on scroll up
867
+ pushing: false,
541
868
 
542
- // top edge
543
- if( (scroll.bottom - element.height) <= element.top) {
544
- module.debug('Bottom fixed rail has reached top of container');
545
- module.setInitialPosition();
546
- }
547
- // bottom edge
548
- else if(scroll.bottom >= context.bottom) {
549
- module.debug('Bottom fixed rail has reached bottom of container');
550
- module.bindBottom();
551
- }
552
- // scroll element if larger than screen
553
- else if(doesntFit) {
554
- module.set.scroll(elementScroll);
555
- module.save.lastScroll(scroll.top);
556
- module.save.elementScroll(elementScroll);
557
- }
869
+ context: false,
870
+ container: false,
558
871
 
559
- }
560
- }
561
- else if( module.is.bottom() ) {
562
- if( scroll.top <= element.top ) {
563
- module.debug('Jumped from bottom fixed to top fixed, most likely used home/end button');
564
- module.setInitialPosition();
565
- }
566
- else {
567
- if(settings.pushing) {
568
- if(module.is.bound() && scroll.bottom <= context.bottom ) {
569
- module.debug('Fixing bottom attached element to bottom of browser.');
570
- module.fixBottom();
571
- }
572
- }
573
- else {
574
- if(module.is.bound() && (scroll.top <= context.bottom - element.height) ) {
575
- module.debug('Fixing bottom attached element to top of browser.');
576
- module.fixTop();
577
- }
578
- }
579
- }
580
- }
581
- }
582
- },
872
+ // Context to watch scroll events
873
+ scrollContext: window,
583
874
 
584
- bindTop: function() {
585
- module.debug('Binding element to top of parent container');
586
- module.remove.offset();
587
- if(settings.setSize) {
588
- module.set.size();
589
- }
590
- $module
591
- .css({
592
- left : '',
593
- top : '',
594
- marginBottom : ''
595
- })
596
- .removeClass(className.fixed)
597
- .removeClass(className.bottom)
598
- .addClass(className.bound)
599
- .addClass(className.top)
600
- ;
601
- settings.onTop.call(element);
602
- settings.onUnstick.call(element);
603
- },
604
- bindBottom: function() {
605
- module.debug('Binding element to bottom of parent container');
606
- module.remove.offset();
607
- if(settings.setSize) {
608
- module.set.size();
609
- }
610
- $module
611
- .css({
612
- left : '',
613
- top : ''
614
- })
615
- .removeClass(className.fixed)
616
- .removeClass(className.top)
617
- .addClass(className.bound)
618
- .addClass(className.bottom)
619
- ;
620
- settings.onBottom.call(element);
621
- settings.onUnstick.call(element);
622
- },
875
+ // Offset to adjust scroll
876
+ offset: 0,
623
877
 
624
- setInitialPosition: function() {
625
- module.debug('Returning to initial position');
626
- module.unfix();
627
- module.unbind();
628
- },
878
+ // Offset to adjust scroll when attached to bottom of screen
879
+ bottomOffset: 0,
629
880
 
881
+ // will only set container height if difference between context and container is larger than this number
882
+ jitter: 5,
630
883
 
631
- fixTop: function() {
632
- module.debug('Fixing element to top of page');
633
- if(settings.setSize) {
634
- module.set.size();
635
- }
636
- module.set.minimumSize();
637
- module.set.offset();
638
- $module
639
- .css({
640
- left : module.cache.element.left,
641
- bottom : '',
642
- marginBottom : ''
643
- })
644
- .removeClass(className.bound)
645
- .removeClass(className.bottom)
646
- .addClass(className.fixed)
647
- .addClass(className.top)
648
- ;
649
- settings.onStick.call(element);
650
- },
884
+ // set width of sticky element when it is fixed to page (used to make sure 100% width is maintained if no fixed size set)
885
+ setSize: true,
651
886
 
652
- fixBottom: function() {
653
- module.debug('Sticking element to bottom of page');
654
- if(settings.setSize) {
655
- module.set.size();
656
- }
657
- module.set.minimumSize();
658
- module.set.offset();
659
- $module
660
- .css({
661
- left : module.cache.element.left,
662
- bottom : '',
663
- marginBottom : ''
664
- })
665
- .removeClass(className.bound)
666
- .removeClass(className.top)
667
- .addClass(className.fixed)
668
- .addClass(className.bottom)
669
- ;
670
- settings.onStick.call(element);
671
- },
887
+ // Whether to automatically observe changes with Mutation Observers
888
+ observeChanges: false,
672
889
 
673
- unbind: function() {
674
- if( module.is.bound() ) {
675
- module.debug('Removing container bound position on element');
676
- module.remove.offset();
677
- $module
678
- .removeClass(className.bound)
679
- .removeClass(className.top)
680
- .removeClass(className.bottom)
681
- ;
682
- }
683
- },
890
+ // Called when position is recalculated
891
+ onReposition: function () {},
684
892
 
685
- unfix: function() {
686
- if( module.is.fixed() ) {
687
- module.debug('Removing fixed position on element');
688
- module.remove.minimumSize();
689
- module.remove.offset();
690
- $module
691
- .removeClass(className.fixed)
692
- .removeClass(className.top)
693
- .removeClass(className.bottom)
694
- ;
695
- settings.onUnstick.call(element);
696
- }
697
- },
893
+ // Called on each scroll
894
+ onScroll: function () {},
698
895
 
699
- reset: function() {
700
- module.debug('Resetting elements position');
701
- module.unbind();
702
- module.unfix();
703
- module.resetCSS();
704
- module.remove.offset();
705
- module.remove.lastScroll();
706
- },
896
+ // Called when element is stuck to viewport
897
+ onStick: function () {},
707
898
 
708
- resetCSS: function() {
709
- $module
710
- .css({
711
- width : '',
712
- height : ''
713
- })
714
- ;
715
- $container
716
- .css({
717
- height: ''
718
- })
719
- ;
720
- },
899
+ // Called when element is unstuck from viewport
900
+ onUnstick: function () {},
721
901
 
722
- setting: function(name, value) {
723
- if( $.isPlainObject(name) ) {
724
- $.extend(true, settings, name);
725
- }
726
- else if(value !== undefined) {
727
- settings[name] = value;
728
- }
729
- else {
730
- return settings[name];
731
- }
732
- },
733
- internal: function(name, value) {
734
- if( $.isPlainObject(name) ) {
735
- $.extend(true, module, name);
736
- }
737
- else if(value !== undefined) {
738
- module[name] = value;
739
- }
740
- else {
741
- return module[name];
742
- }
743
- },
744
- debug: function() {
745
- if(!settings.silent && settings.debug) {
746
- if(settings.performance) {
747
- module.performance.log(arguments);
748
- }
749
- else {
750
- module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
751
- module.debug.apply(console, arguments);
752
- }
753
- }
754
- },
755
- verbose: function() {
756
- if(!settings.silent && settings.verbose && settings.debug) {
757
- if(settings.performance) {
758
- module.performance.log(arguments);
759
- }
760
- else {
761
- module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
762
- module.verbose.apply(console, arguments);
763
- }
764
- }
765
- },
766
- error: function() {
767
- if(!settings.silent) {
768
- module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
769
- module.error.apply(console, arguments);
770
- }
902
+ // Called when element reaches top of context
903
+ onTop: function () {},
904
+
905
+ // Called when element reaches bottom of context
906
+ onBottom: function () {},
907
+
908
+ error: {
909
+ container: 'Sticky element must be inside a relative container',
910
+ visible: 'Element is hidden, you must call refresh after element becomes visible. Use silent setting to suppress this warning in production.',
911
+ method: 'The method you called is not defined.',
912
+ invalidContext: 'Context specified does not exist',
913
+ elementSize: 'Sticky element is larger than its container, cannot create sticky.',
771
914
  },
772
- performance: {
773
- log: function(message) {
774
- var
775
- currentTime,
776
- executionTime,
777
- previousTime
778
- ;
779
- if(settings.performance) {
780
- currentTime = new Date().getTime();
781
- previousTime = time || currentTime;
782
- executionTime = currentTime - previousTime;
783
- time = currentTime;
784
- performance.push({
785
- 'Name' : message[0],
786
- 'Arguments' : [].slice.call(message, 1) || '',
787
- 'Element' : element,
788
- 'Execution Time' : executionTime
789
- });
790
- }
791
- clearTimeout(module.performance.timer);
792
- module.performance.timer = setTimeout(module.performance.display, 0);
793
- },
794
- display: function() {
795
- var
796
- title = settings.name + ':',
797
- totalTime = 0
798
- ;
799
- time = false;
800
- clearTimeout(module.performance.timer);
801
- $.each(performance, function(index, data) {
802
- totalTime += data['Execution Time'];
803
- });
804
- title += ' ' + totalTime + 'ms';
805
- if(moduleSelector) {
806
- title += ' \'' + moduleSelector + '\'';
807
- }
808
- if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
809
- console.groupCollapsed(title);
810
- if(console.table) {
811
- console.table(performance);
812
- }
813
- else {
814
- $.each(performance, function(index, data) {
815
- console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
816
- });
817
- }
818
- console.groupEnd();
819
- }
820
- performance = [];
821
- }
915
+
916
+ className: {
917
+ bound: 'bound',
918
+ fixed: 'fixed',
919
+ supported: 'native',
920
+ top: 'top',
921
+ bottom: 'bottom',
822
922
  },
823
- invoke: function(query, passedArguments, context) {
824
- var
825
- object = instance,
826
- maxDepth,
827
- found,
828
- response
829
- ;
830
- passedArguments = passedArguments || queryArguments;
831
- context = context || element;
832
- if(typeof query == 'string' && object !== undefined) {
833
- query = query.split(/[\. ]/);
834
- maxDepth = query.length - 1;
835
- $.each(query, function(depth, value) {
836
- var camelCaseValue = (depth != maxDepth)
837
- ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
838
- : query
839
- ;
840
- if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
841
- object = object[camelCaseValue];
842
- }
843
- else if( object[camelCaseValue] !== undefined ) {
844
- found = object[camelCaseValue];
845
- return false;
846
- }
847
- else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
848
- object = object[value];
849
- }
850
- else if( object[value] !== undefined ) {
851
- found = object[value];
852
- return false;
853
- }
854
- else {
855
- return false;
856
- }
857
- });
858
- }
859
- if ( isFunction( found ) ) {
860
- response = found.apply(context, passedArguments);
861
- }
862
- else if(found !== undefined) {
863
- response = found;
864
- }
865
- if(Array.isArray(returnedValue)) {
866
- returnedValue.push(response);
867
- }
868
- else if(returnedValue !== undefined) {
869
- returnedValue = [returnedValue, response];
870
- }
871
- else if(response !== undefined) {
872
- returnedValue = response;
873
- }
874
- return found;
875
- }
876
- };
877
-
878
- if(methodInvoked) {
879
- if(instance === undefined) {
880
- module.initialize();
881
- }
882
- module.invoke(query);
883
- }
884
- else {
885
- if(instance !== undefined) {
886
- instance.invoke('destroy');
887
- }
888
- module.initialize();
889
- }
890
- })
891
- ;
892
-
893
- return (returnedValue !== undefined)
894
- ? returnedValue
895
- : this
896
- ;
897
- };
898
-
899
- $.fn.sticky.settings = {
900
-
901
- name : 'Sticky',
902
- namespace : 'sticky',
903
-
904
- silent : false,
905
- debug : false,
906
- verbose : true,
907
- performance : true,
908
-
909
- // whether to stick in the opposite direction on scroll up
910
- pushing : false,
911
-
912
- context : false,
913
- container : false,
914
-
915
- // Context to watch scroll events
916
- scrollContext : window,
917
-
918
- // Offset to adjust scroll
919
- offset : 0,
920
-
921
- // Offset to adjust scroll when attached to bottom of screen
922
- bottomOffset : 0,
923
-
924
- // will only set container height if difference between context and container is larger than this number
925
- jitter : 5,
926
-
927
- // set width of sticky element when it is fixed to page (used to make sure 100% width is maintained if no fixed size set)
928
- setSize : true,
929
-
930
- // Whether to automatically observe changes with Mutation Observers
931
- observeChanges : false,
932
-
933
- // Called when position is recalculated
934
- onReposition : function(){},
935
-
936
- // Called on each scroll
937
- onScroll : function(){},
938
-
939
- // Called when element is stuck to viewport
940
- onStick : function(){},
941
-
942
- // Called when element is unstuck from viewport
943
- onUnstick : function(){},
944
-
945
- // Called when element reaches top of context
946
- onTop : function(){},
947
-
948
- // Called when element reaches bottom of context
949
- onBottom : function(){},
950
-
951
- error : {
952
- container : 'Sticky element must be inside a relative container',
953
- visible : 'Element is hidden, you must call refresh after element becomes visible. Use silent setting to suppress this warning in production.',
954
- method : 'The method you called is not defined.',
955
- invalidContext : 'Context specified does not exist',
956
- elementSize : 'Sticky element is larger than its container, cannot create sticky.'
957
- },
958
-
959
- className : {
960
- bound : 'bound',
961
- fixed : 'fixed',
962
- supported : 'native',
963
- top : 'top',
964
- bottom : 'bottom'
965
- }
966
-
967
- };
968
-
969
- })( jQuery, window, document );
923
+
924
+ };
925
+ })(jQuery, window, document);