fomantic-ui 2.9.1-beta.17 → 2.9.1-beta.19

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