fomantic-ui 2.9.1-beta.17 → 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 -4238
  37. package/dist/components/dropdown.min.css +2 -2
  38. package/dist/components/dropdown.min.js +1 -1
  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 -29479
  153. package/dist/semantic.min.css +2 -2
  154. package/dist/semantic.min.js +1 -1
  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 -4237
  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
@@ -8,962 +8,918 @@
8
8
  *
9
9
  */
10
10
 
11
- ;(function ($, window, document, undefined) {
12
-
13
- 'use strict';
14
-
15
- function isFunction(obj) {
16
- return typeof obj === "function" && typeof obj.nodeType !== "number";
17
- }
18
-
19
- window = (typeof window != 'undefined' && window.Math == Math)
20
- ? window
21
- : (typeof self != 'undefined' && self.Math == Math)
22
- ? self
23
- : Function('return this')()
24
- ;
25
-
26
- $.fn.sticky = function(parameters) {
27
- var
28
- $allModules = $(this),
29
- $document = $(document),
30
- moduleSelector = $allModules.selector || '',
31
-
32
- time = new Date().getTime(),
33
- performance = [],
34
-
35
- query = arguments[0],
36
- methodInvoked = (typeof query == 'string'),
37
- queryArguments = [].slice.call(arguments, 1),
38
- returnedValue
39
- ;
40
-
41
- $allModules
42
- .each(function() {
43
- var
44
- settings = ( $.isPlainObject(parameters) )
45
- ? $.extend(true, {}, $.fn.sticky.settings, parameters)
46
- : $.extend({}, $.fn.sticky.settings),
47
-
48
- className = settings.className,
49
- namespace = settings.namespace,
50
- error = settings.error,
51
-
52
- eventNamespace = '.' + namespace,
53
- moduleNamespace = 'module-' + namespace,
54
-
55
- $module = $(this),
56
- $window = $(window),
57
- $scroll = [window,document].indexOf(settings.scrollContext) < 0 ? $document.find(settings.scrollContext) : $(settings.scrollContext),
58
- $container,
59
- $context,
60
-
61
- instance = $module.data(moduleNamespace),
62
-
63
- requestAnimationFrame = window.requestAnimationFrame
64
- || window.mozRequestAnimationFrame
65
- || window.webkitRequestAnimationFrame
66
- || window.msRequestAnimationFrame
67
- || function(callback) { setTimeout(callback, 0); },
68
-
69
- element = this,
70
-
71
- documentObserver,
72
- observer,
73
- module
74
- ;
75
-
76
- module = {
77
-
78
- initialize: function() {
79
-
80
- module.determineContainer();
81
- module.determineContext();
82
- module.verbose('Initializing sticky', settings, $container);
83
-
84
- module.save.positions();
85
- module.checkErrors();
86
- module.bind.events();
87
-
88
- if(settings.observeChanges) {
89
- module.observeChanges();
90
- }
91
- module.instantiate();
92
- },
11
+ (function ($, window, document, undefined) {
12
+ 'use strict';
13
+
14
+ function isFunction(obj) {
15
+ return typeof obj === 'function' && typeof obj.nodeType !== 'number';
16
+ }
17
+
18
+ window = (typeof window != 'undefined' && window.Math == Math)
19
+ ? window
20
+ : (typeof self != 'undefined' && self.Math == Math)
21
+ ? self
22
+ : Function('return this')();
23
+
24
+ $.fn.sticky = function (parameters) {
25
+ var
26
+ $allModules = $(this),
27
+ $document = $(document),
28
+ moduleSelector = $allModules.selector || '',
29
+
30
+ time = new Date().getTime(),
31
+ performance = [],
32
+
33
+ query = arguments[0],
34
+ methodInvoked = (typeof query == 'string'),
35
+ queryArguments = [].slice.call(arguments, 1),
36
+ returnedValue
37
+ ;
38
+
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
+ ;
93
74
 
94
- instantiate: function() {
95
- module.verbose('Storing instance of module', module);
96
- instance = module;
97
- $module
98
- .data(moduleNamespace, module)
99
- ;
100
- },
75
+ module = {
101
76
 
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
- },
77
+ initialize: function () {
78
+ module.determineContainer();
79
+ module.determineContext();
80
+ module.verbose('Initializing sticky', settings, $container);
120
81
 
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
- },
82
+ module.save.positions();
83
+ module.checkErrors();
84
+ module.bind.events();
140
85
 
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
- },
86
+ if (settings.observeChanges) {
87
+ module.observeChanges();
88
+ }
89
+ module.instantiate();
90
+ },
149
91
 
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
- },
92
+ instantiate: function () {
93
+ module.verbose('Storing instance of module', module);
94
+ instance = module;
95
+ $module
96
+ .data(moduleNamespace, module)
97
+ ;
98
+ },
161
99
 
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
- },
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
+ },
171
118
 
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
- },
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
+ },
186
138
 
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
- },
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
+ },
225
146
 
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
- },
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
+ },
238
157
 
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
- },
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
+ },
248
167
 
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');
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
+ },
277
182
 
278
- scrollContext.top = $scroll.scrollTop();
279
- scrollContext.left = $scroll.scrollLeft();
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
+ },
280
221
 
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();
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
+ },
307
234
 
308
- module.stick();
309
- module.debug('Caching element positions', module.cache);
310
- }
311
- },
235
+ supports: {
236
+ sticky: function () {
237
+ var
238
+ $element = $('<div/>')
239
+ ;
240
+ $element.addClass(className.supported);
312
241
 
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
- },
242
+ return ($element.css('position').match('sticky'));
243
+ },
244
+ },
340
245
 
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
- },
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
+ },
363
309
 
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
- },
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
+ },
380
360
 
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');
448
- }
449
- }
450
- },
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
+ },
451
377
 
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
- },
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
+ },
475
446
 
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
- }
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
+ },
517
470
 
518
- }
519
- else if( module.is.fixed() ) {
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
+ },
520
555
 
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
- }
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
+ },
538
595
 
539
- // currently fixed bottom
540
- else if(module.is.bottom() ) {
596
+ setInitialPosition: function () {
597
+ module.debug('Returning to initial position');
598
+ module.unfix();
599
+ module.unbind();
600
+ },
541
601
 
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
- }
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
+ },
558
622
 
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
- }
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
+ },
643
+
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
+ },
655
+
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
+ },
669
+
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
+ },
678
+
679
+ resetCSS: function () {
680
+ $module
681
+ .css({
682
+ width: '',
683
+ height: '',
684
+ })
685
+ ;
686
+ $container
687
+ .css({
688
+ height: '',
689
+ })
690
+ ;
691
+ },
692
+
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
+ };
837
+
838
+ if (methodInvoked) {
839
+ if (instance === undefined) {
840
+ module.initialize();
572
841
  }
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
- }
842
+ module.invoke(query);
843
+ } else {
844
+ if (instance !== undefined) {
845
+ instance.invoke('destroy');
578
846
  }
579
- }
847
+ module.initialize();
580
848
  }
581
- }
582
- },
849
+ });
583
850
 
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
- },
851
+ return (returnedValue !== undefined)
852
+ ? returnedValue
853
+ : this;
854
+ };
623
855
 
624
- setInitialPosition: function() {
625
- module.debug('Returning to initial position');
626
- module.unfix();
627
- module.unbind();
628
- },
856
+ $.fn.sticky.settings = {
629
857
 
858
+ name: 'Sticky',
859
+ namespace: 'sticky',
630
860
 
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
- },
861
+ silent: false,
862
+ debug: false,
863
+ verbose: true,
864
+ performance: true,
651
865
 
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
- },
866
+ // whether to stick in the opposite direction on scroll up
867
+ pushing: false,
672
868
 
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
- },
869
+ context: false,
870
+ container: false,
684
871
 
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
- },
872
+ // Context to watch scroll events
873
+ scrollContext: window,
698
874
 
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
- },
875
+ // Offset to adjust scroll
876
+ offset: 0,
707
877
 
708
- resetCSS: function() {
709
- $module
710
- .css({
711
- width : '',
712
- height : ''
713
- })
714
- ;
715
- $container
716
- .css({
717
- height: ''
718
- })
719
- ;
720
- },
878
+ // Offset to adjust scroll when attached to bottom of screen
879
+ bottomOffset: 0,
721
880
 
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
- }
881
+ // will only set container height if difference between context and container is larger than this number
882
+ jitter: 5,
883
+
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,
886
+
887
+ // Whether to automatically observe changes with Mutation Observers
888
+ observeChanges: false,
889
+
890
+ // Called when position is recalculated
891
+ onReposition: function () {},
892
+
893
+ // Called on each scroll
894
+ onScroll: function () {},
895
+
896
+ // Called when element is stuck to viewport
897
+ onStick: function () {},
898
+
899
+ // Called when element is unstuck from viewport
900
+ onUnstick: function () {},
901
+
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);