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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (252) hide show
  1. package/.eslintrc.js +109 -0
  2. package/.github/workflows/ci.yml +13 -3
  3. package/dist/components/accordion.css +1 -1
  4. package/dist/components/accordion.js +571 -598
  5. package/dist/components/accordion.min.css +1 -1
  6. package/dist/components/accordion.min.js +1 -1
  7. package/dist/components/ad.css +1 -1
  8. package/dist/components/ad.min.css +1 -1
  9. package/dist/components/api.js +1164 -1186
  10. package/dist/components/api.min.js +1 -1
  11. package/dist/components/breadcrumb.css +1 -1
  12. package/dist/components/breadcrumb.min.css +1 -1
  13. package/dist/components/button.css +1 -1
  14. package/dist/components/button.min.css +1 -1
  15. package/dist/components/calendar.css +1 -1
  16. package/dist/components/calendar.js +1897 -1818
  17. package/dist/components/calendar.min.css +1 -1
  18. package/dist/components/calendar.min.js +1 -1
  19. package/dist/components/card.css +1 -1
  20. package/dist/components/card.min.css +1 -1
  21. package/dist/components/checkbox.css +1 -1
  22. package/dist/components/checkbox.js +844 -841
  23. package/dist/components/checkbox.min.css +1 -1
  24. package/dist/components/checkbox.min.js +1 -1
  25. package/dist/components/comment.css +1 -1
  26. package/dist/components/comment.min.css +1 -1
  27. package/dist/components/container.css +3 -1
  28. package/dist/components/container.min.css +2 -2
  29. package/dist/components/dimmer.css +1 -1
  30. package/dist/components/dimmer.js +710 -737
  31. package/dist/components/dimmer.min.css +1 -1
  32. package/dist/components/dimmer.min.js +1 -1
  33. package/dist/components/divider.css +1 -1
  34. package/dist/components/divider.min.css +1 -1
  35. package/dist/components/dropdown.css +11 -8
  36. package/dist/components/dropdown.js +4163 -4234
  37. package/dist/components/dropdown.min.css +2 -2
  38. package/dist/components/dropdown.min.js +2 -2
  39. package/dist/components/embed.css +1 -1
  40. package/dist/components/embed.js +653 -675
  41. package/dist/components/embed.min.css +1 -1
  42. package/dist/components/embed.min.js +1 -1
  43. package/dist/components/feed.css +1 -1
  44. package/dist/components/feed.min.css +1 -1
  45. package/dist/components/flag.css +1 -1
  46. package/dist/components/flag.min.css +1 -1
  47. package/dist/components/flyout.css +6 -3
  48. package/dist/components/flyout.js +1466 -1467
  49. package/dist/components/flyout.min.css +2 -2
  50. package/dist/components/flyout.min.js +1 -1
  51. package/dist/components/form.css +1 -1
  52. package/dist/components/form.js +1981 -2004
  53. package/dist/components/form.min.css +1 -1
  54. package/dist/components/form.min.js +1 -1
  55. package/dist/components/grid.css +1 -1
  56. package/dist/components/grid.min.css +1 -1
  57. package/dist/components/header.css +1 -1
  58. package/dist/components/header.min.css +1 -1
  59. package/dist/components/icon.css +1 -1
  60. package/dist/components/icon.min.css +1 -1
  61. package/dist/components/image.css +1 -1
  62. package/dist/components/image.min.css +1 -1
  63. package/dist/components/input.css +1 -1
  64. package/dist/components/input.min.css +1 -1
  65. package/dist/components/item.css +1 -1
  66. package/dist/components/item.min.css +1 -1
  67. package/dist/components/label.css +1 -1
  68. package/dist/components/label.min.css +1 -1
  69. package/dist/components/list.css +1 -1
  70. package/dist/components/list.min.css +1 -1
  71. package/dist/components/loader.css +1 -1
  72. package/dist/components/loader.min.css +1 -1
  73. package/dist/components/message.css +1 -1
  74. package/dist/components/message.min.css +1 -1
  75. package/dist/components/modal.css +7 -1
  76. package/dist/components/modal.js +1493 -1487
  77. package/dist/components/modal.min.css +2 -2
  78. package/dist/components/modal.min.js +1 -1
  79. package/dist/components/nag.css +1 -1
  80. package/dist/components/nag.js +520 -529
  81. package/dist/components/nag.min.css +1 -1
  82. package/dist/components/nag.min.js +1 -1
  83. package/dist/components/placeholder.css +1 -1
  84. package/dist/components/placeholder.min.css +1 -1
  85. package/dist/components/popup.css +1 -1
  86. package/dist/components/popup.js +1439 -1456
  87. package/dist/components/popup.min.css +1 -1
  88. package/dist/components/popup.min.js +1 -1
  89. package/dist/components/progress.css +1 -1
  90. package/dist/components/progress.js +971 -997
  91. package/dist/components/progress.min.css +1 -1
  92. package/dist/components/progress.min.js +1 -1
  93. package/dist/components/rail.css +1 -1
  94. package/dist/components/rail.min.css +1 -1
  95. package/dist/components/rating.css +1 -1
  96. package/dist/components/rating.js +508 -524
  97. package/dist/components/rating.min.css +1 -1
  98. package/dist/components/rating.min.js +1 -1
  99. package/dist/components/reset.css +1 -1
  100. package/dist/components/reset.min.css +1 -1
  101. package/dist/components/reveal.css +1 -1
  102. package/dist/components/reveal.min.css +1 -1
  103. package/dist/components/search.css +3 -1
  104. package/dist/components/search.js +1500 -1534
  105. package/dist/components/search.min.css +2 -2
  106. package/dist/components/search.min.js +1 -1
  107. package/dist/components/segment.css +3 -1
  108. package/dist/components/segment.min.css +2 -2
  109. package/dist/components/shape.css +1 -1
  110. package/dist/components/shape.js +794 -809
  111. package/dist/components/shape.min.css +1 -1
  112. package/dist/components/shape.min.js +1 -1
  113. package/dist/components/sidebar.css +3 -1
  114. package/dist/components/sidebar.js +1079 -1104
  115. package/dist/components/sidebar.min.css +2 -2
  116. package/dist/components/sidebar.min.js +1 -1
  117. package/dist/components/site.css +1 -1
  118. package/dist/components/site.js +457 -472
  119. package/dist/components/site.min.css +1 -1
  120. package/dist/components/site.min.js +1 -1
  121. package/dist/components/slider.js +1289 -1311
  122. package/dist/components/slider.min.js +1 -1
  123. package/dist/components/state.js +641 -657
  124. package/dist/components/state.min.js +1 -1
  125. package/dist/components/statistic.css +1 -1
  126. package/dist/components/statistic.min.css +1 -1
  127. package/dist/components/step.css +1 -1
  128. package/dist/components/step.min.css +1 -1
  129. package/dist/components/sticky.css +1 -1
  130. package/dist/components/sticky.js +859 -903
  131. package/dist/components/sticky.min.css +1 -1
  132. package/dist/components/sticky.min.js +1 -1
  133. package/dist/components/tab.css +1 -1
  134. package/dist/components/tab.js +923 -963
  135. package/dist/components/tab.min.css +1 -1
  136. package/dist/components/tab.min.js +1 -1
  137. package/dist/components/table.css +5 -1
  138. package/dist/components/table.min.css +2 -2
  139. package/dist/components/text.css +1 -1
  140. package/dist/components/text.min.css +1 -1
  141. package/dist/components/toast.css +1 -1
  142. package/dist/components/toast.js +889 -891
  143. package/dist/components/toast.min.css +1 -1
  144. package/dist/components/toast.min.js +1 -1
  145. package/dist/components/transition.css +1 -1
  146. package/dist/components/transition.js +1043 -1077
  147. package/dist/components/transition.min.css +1 -1
  148. package/dist/components/transition.min.js +1 -1
  149. package/dist/components/visibility.js +1222 -1244
  150. package/dist/components/visibility.min.js +1 -1
  151. package/dist/semantic.css +84 -60
  152. package/dist/semantic.js +29033 -29475
  153. package/dist/semantic.min.css +2 -2
  154. package/dist/semantic.min.js +2 -2
  155. package/examples/assets/show-examples.js +13 -13
  156. package/gulpfile.js +9 -10
  157. package/package.json +5 -2
  158. package/scripts/nightly-version.js +81 -75
  159. package/src/definitions/behaviors/api.js +1163 -1185
  160. package/src/definitions/behaviors/form.js +1980 -2003
  161. package/src/definitions/behaviors/state.js +647 -663
  162. package/src/definitions/behaviors/visibility.js +1221 -1243
  163. package/src/definitions/collections/table.less +2 -0
  164. package/src/definitions/elements/container.less +1 -0
  165. package/src/definitions/elements/segment.less +1 -0
  166. package/src/definitions/globals/site.js +456 -471
  167. package/src/definitions/modules/accordion.js +570 -597
  168. package/src/definitions/modules/calendar.js +1896 -1817
  169. package/src/definitions/modules/checkbox.js +849 -846
  170. package/src/definitions/modules/dimmer.js +709 -736
  171. package/src/definitions/modules/dropdown.js +4162 -4233
  172. package/src/definitions/modules/dropdown.less +5 -8
  173. package/src/definitions/modules/embed.js +652 -674
  174. package/src/definitions/modules/flyout.js +1465 -1466
  175. package/src/definitions/modules/flyout.less +15 -12
  176. package/src/definitions/modules/modal.js +1492 -1486
  177. package/src/definitions/modules/modal.less +3 -0
  178. package/src/definitions/modules/nag.js +519 -528
  179. package/src/definitions/modules/popup.js +1438 -1455
  180. package/src/definitions/modules/progress.js +970 -996
  181. package/src/definitions/modules/rating.js +507 -523
  182. package/src/definitions/modules/search.js +1499 -1533
  183. package/src/definitions/modules/search.less +1 -0
  184. package/src/definitions/modules/shape.js +801 -816
  185. package/src/definitions/modules/sidebar.js +1078 -1103
  186. package/src/definitions/modules/sidebar.less +1 -0
  187. package/src/definitions/modules/slider.js +1288 -1310
  188. package/src/definitions/modules/sticky.js +875 -919
  189. package/src/definitions/modules/tab.js +922 -962
  190. package/src/definitions/modules/toast.js +888 -890
  191. package/src/definitions/modules/transition.js +1048 -1082
  192. package/src/themes/default/elements/container.variables +0 -7
  193. package/src/themes/default/elements/segment.variables +0 -7
  194. package/src/themes/default/globals/site.variables +7 -0
  195. package/src/themes/default/globals/variation.variables +1 -0
  196. package/tasks/admin/components/create.js +274 -276
  197. package/tasks/admin/components/init.js +123 -130
  198. package/tasks/admin/components/update.js +149 -157
  199. package/tasks/admin/distributions/create.js +184 -187
  200. package/tasks/admin/distributions/init.js +123 -130
  201. package/tasks/admin/distributions/update.js +145 -152
  202. package/tasks/admin/publish.js +5 -7
  203. package/tasks/admin/register.js +36 -38
  204. package/tasks/admin/release.js +8 -10
  205. package/tasks/build/assets.js +42 -39
  206. package/tasks/build/css.js +225 -216
  207. package/tasks/build/javascript.js +118 -113
  208. package/tasks/build.js +10 -10
  209. package/tasks/check-install.js +14 -16
  210. package/tasks/clean.js +5 -5
  211. package/tasks/collections/admin.js +34 -36
  212. package/tasks/collections/build.js +18 -20
  213. package/tasks/collections/docs.js +9 -11
  214. package/tasks/collections/install.js +9 -11
  215. package/tasks/collections/rtl.js +9 -11
  216. package/tasks/collections/various.js +8 -10
  217. package/tasks/config/admin/github.js +17 -17
  218. package/tasks/config/admin/oauth.example.js +4 -4
  219. package/tasks/config/admin/release.js +98 -98
  220. package/tasks/config/admin/templates/component-package.js +9 -10
  221. package/tasks/config/admin/templates/css-package.js +18 -20
  222. package/tasks/config/admin/templates/less-package.js +11 -13
  223. package/tasks/config/defaults.js +116 -116
  224. package/tasks/config/docs.js +23 -23
  225. package/tasks/config/npm/gulpfile.js +8 -9
  226. package/tasks/config/project/config.js +127 -134
  227. package/tasks/config/project/install.js +715 -713
  228. package/tasks/config/project/release.js +32 -38
  229. package/tasks/config/tasks.js +163 -164
  230. package/tasks/config/user.js +23 -29
  231. package/tasks/docs/build.js +97 -95
  232. package/tasks/docs/metadata.js +90 -96
  233. package/tasks/docs/serve.js +80 -81
  234. package/tasks/install.js +370 -378
  235. package/tasks/rtl/build.js +2 -2
  236. package/tasks/rtl/watch.js +2 -2
  237. package/tasks/version.js +4 -4
  238. package/tasks/watch.js +28 -30
  239. package/test/meteor/assets.js +10 -13
  240. package/test/meteor/fonts.js +12 -13
  241. package/test/modules/accordion.spec.js +6 -8
  242. package/test/modules/checkbox.spec.js +5 -7
  243. package/test/modules/dropdown.spec.js +5 -7
  244. package/test/modules/modal.spec.js +6 -8
  245. package/test/modules/module.spec.js +158 -178
  246. package/test/modules/popup.spec.js +5 -7
  247. package/test/modules/search.spec.js +5 -7
  248. package/test/modules/shape.spec.js +5 -7
  249. package/test/modules/sidebar.spec.js +5 -7
  250. package/test/modules/tab.spec.js +6 -8
  251. package/test/modules/transition.spec.js +5 -7
  252. package/test/modules/video.spec.js +5 -7
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * # Fomantic-UI 2.9.1-beta.16+7071e59 - Visibility
2
+ * # Fomantic-UI 2.9.1-beta.18+935e235 - Visibility
3
3
  * https://github.com/fomantic/Fomantic-UI/
4
4
  *
5
5
  *
@@ -8,1306 +8,1284 @@
8
8
  *
9
9
  */
10
10
 
11
- ;(function ($, window, document, undefined) {
11
+ (function ($, window, document, undefined) {
12
+ 'use strict';
12
13
 
13
- 'use strict';
14
+ function isFunction(obj) {
15
+ return typeof obj === 'function' && typeof obj.nodeType !== 'number';
16
+ }
14
17
 
15
- function isFunction(obj) {
16
- return typeof obj === "function" && typeof obj.nodeType !== "number";
17
- }
18
+ window = (typeof window != 'undefined' && window.Math == Math)
19
+ ? window
20
+ : (typeof self != 'undefined' && self.Math == Math)
21
+ ? self
22
+ : Function('return this')();
18
23
 
19
- window = (typeof window != 'undefined' && window.Math == Math)
20
- ? window
21
- : (typeof self != 'undefined' && self.Math == Math)
22
- ? self
23
- : Function('return this')()
24
- ;
24
+ $.fn.visibility = function (parameters) {
25
+ var
26
+ $allModules = $(this),
27
+ moduleSelector = $allModules.selector || '',
25
28
 
26
- $.fn.visibility = function(parameters) {
27
- var
28
- $allModules = $(this),
29
- moduleSelector = $allModules.selector || '',
29
+ time = new Date().getTime(),
30
+ performance = [],
30
31
 
31
- time = new Date().getTime(),
32
- performance = [],
32
+ query = arguments[0],
33
+ methodInvoked = (typeof query == 'string'),
34
+ queryArguments = [].slice.call(arguments, 1),
35
+ returnedValue,
33
36
 
34
- query = arguments[0],
35
- methodInvoked = (typeof query == 'string'),
36
- queryArguments = [].slice.call(arguments, 1),
37
- returnedValue,
37
+ moduleCount = $allModules.length,
38
+ loadedCount = 0
39
+ ;
38
40
 
39
- moduleCount = $allModules.length,
40
- loadedCount = 0
41
- ;
42
-
43
- $allModules
44
- .each(function() {
45
- var
46
- settings = ( $.isPlainObject(parameters) )
47
- ? $.extend(true, {}, $.fn.visibility.settings, parameters)
48
- : $.extend({}, $.fn.visibility.settings),
49
-
50
- className = settings.className,
51
- namespace = settings.namespace,
52
- error = settings.error,
53
- metadata = settings.metadata,
54
-
55
- eventNamespace = '.' + namespace,
56
- moduleNamespace = 'module-' + namespace,
57
-
58
- $window = $(window),
59
-
60
- $module = $(this),
61
- $context = [window,document].indexOf(settings.context) < 0 ? $(document).find(settings.context) : $(settings.context),
62
-
63
- $placeholder,
64
-
65
- instance = $module.data(moduleNamespace),
66
-
67
- requestAnimationFrame = window.requestAnimationFrame
68
- || window.mozRequestAnimationFrame
69
- || window.webkitRequestAnimationFrame
70
- || window.msRequestAnimationFrame
71
- || function(callback) { setTimeout(callback, 0); },
72
-
73
- element = this,
74
- disabled = false,
75
-
76
- contextObserver,
77
- observer,
78
- module
79
- ;
80
-
81
- module = {
41
+ $allModules.each(function () {
42
+ var
43
+ settings = ($.isPlainObject(parameters))
44
+ ? $.extend(true, {}, $.fn.visibility.settings, parameters)
45
+ : $.extend({}, $.fn.visibility.settings),
82
46
 
83
- initialize: function() {
84
- module.debug('Initializing', settings);
47
+ className = settings.className,
48
+ namespace = settings.namespace,
49
+ error = settings.error,
50
+ metadata = settings.metadata,
85
51
 
86
- module.setup.cache();
52
+ eventNamespace = '.' + namespace,
53
+ moduleNamespace = 'module-' + namespace,
87
54
 
88
- if( module.should.trackChanges() ) {
55
+ $window = $(window),
89
56
 
90
- if(settings.type == 'image') {
91
- module.setup.image();
92
- }
93
- if(settings.type == 'fixed') {
94
- module.setup.fixed();
95
- }
57
+ $module = $(this),
58
+ $context = [window, document].indexOf(settings.context) < 0 ? $(document).find(settings.context) : $(settings.context),
96
59
 
97
- if(settings.observeChanges) {
98
- module.observeChanges();
99
- }
100
- module.bind.events();
101
- }
102
-
103
- module.save.position();
104
- if( !module.is.visible() ) {
105
- module.error(error.visible, $module);
106
- }
107
-
108
- if(settings.initialCheck) {
109
- module.checkVisibility();
110
- }
111
- module.instantiate();
112
- },
60
+ $placeholder,
113
61
 
114
- instantiate: function() {
115
- module.debug('Storing instance', module);
116
- $module
117
- .data(moduleNamespace, module)
118
- ;
119
- instance = module;
120
- },
62
+ instance = $module.data(moduleNamespace),
121
63
 
122
- destroy: function() {
123
- module.verbose('Destroying previous module');
124
- if(observer) {
125
- observer.disconnect();
126
- }
127
- if(contextObserver) {
128
- contextObserver.disconnect();
129
- }
130
- $window
131
- .off('load' + eventNamespace, module.event.load)
132
- .off('resize' + eventNamespace, module.event.resize)
133
- ;
134
- $context
135
- .off('scroll' + eventNamespace, module.event.scroll)
136
- .off('scrollchange' + eventNamespace, module.event.scrollchange)
137
- ;
138
- if(settings.type == 'fixed') {
139
- module.resetFixed();
140
- module.remove.placeholder();
141
- }
142
- $module
143
- .off(eventNamespace)
144
- .removeData(moduleNamespace)
145
- ;
146
- },
64
+ requestAnimationFrame = window.requestAnimationFrame
65
+ || window.mozRequestAnimationFrame
66
+ || window.webkitRequestAnimationFrame
67
+ || window.msRequestAnimationFrame
68
+ || function (callback) {
69
+ setTimeout(callback, 0);
70
+ },
147
71
 
148
- observeChanges: function() {
149
- if('MutationObserver' in window) {
150
- contextObserver = new MutationObserver(module.event.contextChanged);
151
- observer = new MutationObserver(module.event.changed);
152
- contextObserver.observe(document, {
153
- childList : true,
154
- subtree : true
155
- });
156
- observer.observe(element, {
157
- childList : true,
158
- subtree : true
159
- });
160
- module.debug('Setting up mutation observer', observer);
161
- }
162
- },
72
+ element = this,
73
+ disabled = false,
163
74
 
164
- bind: {
165
- events: function() {
166
- module.verbose('Binding visibility events to scroll and resize');
167
- if(settings.refreshOnLoad) {
168
- $window
169
- .on('load' + eventNamespace, module.event.load)
170
- ;
171
- }
172
- $window
173
- .on('resize' + eventNamespace, module.event.resize)
75
+ contextObserver,
76
+ observer,
77
+ module
174
78
  ;
175
- // pub/sub pattern
176
- $context
177
- .off('scroll' + eventNamespace)
178
- .on('scroll' + eventNamespace, module.event.scroll)
179
- .on('scrollchange' + eventNamespace, module.event.scrollchange)
180
- ;
181
- }
182
- },
183
79
 
184
- event: {
185
- changed: function(mutations) {
186
- module.verbose('DOM tree modified, updating visibility calculations');
187
- module.timer = setTimeout(function() {
188
- module.verbose('DOM tree modified, updating sticky menu');
189
- module.refresh();
190
- }, 100);
191
- },
192
- contextChanged: function(mutations) {
193
- [].forEach.call(mutations, function(mutation) {
194
- if(mutation.removedNodes) {
195
- [].forEach.call(mutation.removedNodes, function(node) {
196
- if(node == element || $(node).find(element).length > 0) {
197
- module.debug('Element removed from DOM, tearing down events');
198
- module.destroy();
199
- }
200
- });
201
- }
202
- });
203
- },
204
- resize: function() {
205
- module.debug('Window resized');
206
- if(settings.refreshOnResize) {
207
- requestAnimationFrame(module.refresh);
208
- }
209
- },
210
- load: function() {
211
- module.debug('Page finished loading');
212
- requestAnimationFrame(module.refresh);
213
- },
214
- // publishes scrollchange event on one scroll
215
- scroll: function() {
216
- if(settings.throttle) {
217
- clearTimeout(module.timer);
218
- module.timer = setTimeout(function() {
219
- $context.triggerHandler('scrollchange' + eventNamespace, [ $context.scrollTop() ]);
220
- }, settings.throttle);
221
- }
222
- else {
223
- requestAnimationFrame(function() {
224
- $context.triggerHandler('scrollchange' + eventNamespace, [ $context.scrollTop() ]);
225
- });
226
- }
227
- },
228
- // subscribes to scrollchange
229
- scrollchange: function(event, scrollPosition) {
230
- module.checkVisibility(scrollPosition);
231
- },
232
- },
80
+ module = {
233
81
 
234
- precache: function(images, callback) {
235
- if (!(images instanceof Array)) {
236
- images = [images];
237
- }
238
- var
239
- imagesLength = images.length,
240
- loadedCounter = 0,
241
- cache = [],
242
- cacheImage = document.createElement('img'),
243
- handleLoad = function() {
244
- loadedCounter++;
245
- if (loadedCounter >= images.length) {
246
- if (isFunction(callback)) {
247
- callback();
248
- }
249
- }
250
- }
251
- ;
252
- while (imagesLength--) {
253
- cacheImage = document.createElement('img');
254
- cacheImage.onload = handleLoad;
255
- cacheImage.onerror = handleLoad;
256
- cacheImage.src = images[imagesLength];
257
- cache.push(cacheImage);
258
- }
259
- },
82
+ initialize: function () {
83
+ module.debug('Initializing', settings);
260
84
 
261
- enableCallbacks: function() {
262
- module.debug('Allowing callbacks to occur');
263
- disabled = false;
264
- },
85
+ module.setup.cache();
265
86
 
266
- disableCallbacks: function() {
267
- module.debug('Disabling all callbacks temporarily');
268
- disabled = true;
269
- },
87
+ if (module.should.trackChanges()) {
88
+ if (settings.type == 'image') {
89
+ module.setup.image();
90
+ }
91
+ if (settings.type == 'fixed') {
92
+ module.setup.fixed();
93
+ }
270
94
 
271
- should: {
272
- trackChanges: function() {
273
- if(methodInvoked) {
274
- module.debug('One time query, no need to bind events');
275
- return false;
276
- }
277
- module.debug('Callbacks being attached');
278
- return true;
279
- }
280
- },
95
+ if (settings.observeChanges) {
96
+ module.observeChanges();
97
+ }
98
+ module.bind.events();
99
+ }
281
100
 
282
- setup: {
283
- cache: function() {
284
- module.cache = {
285
- occurred : {},
286
- screen : {},
287
- element : {},
288
- };
289
- },
290
- image: function() {
291
- var
292
- src = $module.data(metadata.src)
293
- ;
294
- if(src) {
295
- module.verbose('Lazy loading image', src);
296
- settings.once = true;
297
- settings.observeChanges = false;
298
-
299
- // show when top visible
300
- settings.onOnScreen = function() {
301
- module.debug('Image on screen', element);
302
- module.precache(src, function() {
303
- module.set.image(src, function() {
304
- loadedCount++;
305
- if(loadedCount == moduleCount) {
306
- settings.onAllLoaded.call(this);
101
+ module.save.position();
102
+ if (!module.is.visible()) {
103
+ module.error(error.visible, $module);
307
104
  }
308
- settings.onLoad.call(this);
309
- });
310
- });
311
- };
312
- }
313
- },
314
- fixed: function() {
315
- module.debug('Setting up fixed');
316
- settings.once = false;
317
- settings.observeChanges = false;
318
- settings.initialCheck = true;
319
- settings.refreshOnLoad = true;
320
- if(!parameters.transition) {
321
- settings.transition = false;
322
- }
323
- module.create.placeholder();
324
- module.debug('Added placeholder', $placeholder);
325
- settings.onTopPassed = function() {
326
- module.debug('Element passed, adding fixed position', $module);
327
- module.show.placeholder();
328
- module.set.fixed();
329
- if(settings.transition) {
330
- if($.fn.transition !== undefined) {
331
- $module.transition(settings.transition, settings.duration);
332
- }
333
- }
334
- };
335
- settings.onTopPassedReverse = function() {
336
- module.debug('Element returned to position, removing fixed', $module);
337
- module.hide.placeholder();
338
- module.remove.fixed();
339
- };
340
- }
341
- },
342
105
 
343
- create: {
344
- placeholder: function() {
345
- module.verbose('Creating fixed position placeholder');
346
- $placeholder = $module
347
- .clone(false)
348
- .css('display', 'none')
349
- .addClass(className.placeholder)
350
- .insertAfter($module)
351
- ;
352
- }
353
- },
106
+ if (settings.initialCheck) {
107
+ module.checkVisibility();
108
+ }
109
+ module.instantiate();
110
+ },
111
+
112
+ instantiate: function () {
113
+ module.debug('Storing instance', module);
114
+ $module
115
+ .data(moduleNamespace, module)
116
+ ;
117
+ instance = module;
118
+ },
119
+
120
+ destroy: function () {
121
+ module.verbose('Destroying previous module');
122
+ if (observer) {
123
+ observer.disconnect();
124
+ }
125
+ if (contextObserver) {
126
+ contextObserver.disconnect();
127
+ }
128
+ $window
129
+ .off('load' + eventNamespace, module.event.load)
130
+ .off('resize' + eventNamespace, module.event.resize)
131
+ ;
132
+ $context
133
+ .off('scroll' + eventNamespace, module.event.scroll)
134
+ .off('scrollchange' + eventNamespace, module.event.scrollchange)
135
+ ;
136
+ if (settings.type == 'fixed') {
137
+ module.resetFixed();
138
+ module.remove.placeholder();
139
+ }
140
+ $module
141
+ .off(eventNamespace)
142
+ .removeData(moduleNamespace)
143
+ ;
144
+ },
145
+
146
+ observeChanges: function () {
147
+ if ('MutationObserver' in window) {
148
+ contextObserver = new MutationObserver(module.event.contextChanged);
149
+ observer = new MutationObserver(module.event.changed);
150
+ contextObserver.observe(document, {
151
+ childList: true,
152
+ subtree: true,
153
+ });
154
+ observer.observe(element, {
155
+ childList: true,
156
+ subtree: true,
157
+ });
158
+ module.debug('Setting up mutation observer', observer);
159
+ }
160
+ },
161
+
162
+ bind: {
163
+ events: function () {
164
+ module.verbose('Binding visibility events to scroll and resize');
165
+ if (settings.refreshOnLoad) {
166
+ $window
167
+ .on('load' + eventNamespace, module.event.load)
168
+ ;
169
+ }
170
+ $window
171
+ .on('resize' + eventNamespace, module.event.resize)
172
+ ;
173
+ // pub/sub pattern
174
+ $context
175
+ .off('scroll' + eventNamespace)
176
+ .on('scroll' + eventNamespace, module.event.scroll)
177
+ .on('scrollchange' + eventNamespace, module.event.scrollchange)
178
+ ;
179
+ },
180
+ },
181
+
182
+ event: {
183
+ changed: function (mutations) {
184
+ module.verbose('DOM tree modified, updating visibility calculations');
185
+ module.timer = setTimeout(function () {
186
+ module.verbose('DOM tree modified, updating sticky menu');
187
+ module.refresh();
188
+ }, 100);
189
+ },
190
+ contextChanged: function (mutations) {
191
+ [].forEach.call(mutations, function (mutation) {
192
+ if (mutation.removedNodes) {
193
+ [].forEach.call(mutation.removedNodes, function (node) {
194
+ if (node == element || $(node).find(element).length > 0) {
195
+ module.debug('Element removed from DOM, tearing down events');
196
+ module.destroy();
197
+ }
198
+ });
199
+ }
200
+ });
201
+ },
202
+ resize: function () {
203
+ module.debug('Window resized');
204
+ if (settings.refreshOnResize) {
205
+ requestAnimationFrame(module.refresh);
206
+ }
207
+ },
208
+ load: function () {
209
+ module.debug('Page finished loading');
210
+ requestAnimationFrame(module.refresh);
211
+ },
212
+ // publishes scrollchange event on one scroll
213
+ scroll: function () {
214
+ if (settings.throttle) {
215
+ clearTimeout(module.timer);
216
+ module.timer = setTimeout(function () {
217
+ $context.triggerHandler('scrollchange' + eventNamespace, [$context.scrollTop()]);
218
+ }, settings.throttle);
219
+ } else {
220
+ requestAnimationFrame(function () {
221
+ $context.triggerHandler('scrollchange' + eventNamespace, [$context.scrollTop()]);
222
+ });
223
+ }
224
+ },
225
+ // subscribes to scrollchange
226
+ scrollchange: function (event, scrollPosition) {
227
+ module.checkVisibility(scrollPosition);
228
+ },
229
+ },
230
+
231
+ precache: function (images, callback) {
232
+ if (!(images instanceof Array)) {
233
+ images = [images];
234
+ }
235
+ var
236
+ imagesLength = images.length,
237
+ loadedCounter = 0,
238
+ cache = [],
239
+ cacheImage = document.createElement('img'),
240
+ handleLoad = function () {
241
+ loadedCounter++;
242
+ if (loadedCounter >= images.length) {
243
+ if (isFunction(callback)) {
244
+ callback();
245
+ }
246
+ }
247
+ }
248
+ ;
249
+ while (imagesLength--) {
250
+ cacheImage = document.createElement('img');
251
+ cacheImage.onload = handleLoad;
252
+ cacheImage.onerror = handleLoad;
253
+ cacheImage.src = images[imagesLength];
254
+ cache.push(cacheImage);
255
+ }
256
+ },
257
+
258
+ enableCallbacks: function () {
259
+ module.debug('Allowing callbacks to occur');
260
+ disabled = false;
261
+ },
262
+
263
+ disableCallbacks: function () {
264
+ module.debug('Disabling all callbacks temporarily');
265
+ disabled = true;
266
+ },
267
+
268
+ should: {
269
+ trackChanges: function () {
270
+ if (methodInvoked) {
271
+ module.debug('One time query, no need to bind events');
272
+
273
+ return false;
274
+ }
275
+ module.debug('Callbacks being attached');
276
+
277
+ return true;
278
+ },
279
+ },
280
+
281
+ setup: {
282
+ cache: function () {
283
+ module.cache = {
284
+ occurred: {},
285
+ screen: {},
286
+ element: {},
287
+ };
288
+ },
289
+ image: function () {
290
+ var
291
+ src = $module.data(metadata.src)
292
+ ;
293
+ if (src) {
294
+ module.verbose('Lazy loading image', src);
295
+ settings.once = true;
296
+ settings.observeChanges = false;
297
+
298
+ // show when top visible
299
+ settings.onOnScreen = function () {
300
+ module.debug('Image on screen', element);
301
+ module.precache(src, function () {
302
+ module.set.image(src, function () {
303
+ loadedCount++;
304
+ if (loadedCount == moduleCount) {
305
+ settings.onAllLoaded.call(this);
306
+ }
307
+ settings.onLoad.call(this);
308
+ });
309
+ });
310
+ };
311
+ }
312
+ },
313
+ fixed: function () {
314
+ module.debug('Setting up fixed');
315
+ settings.once = false;
316
+ settings.observeChanges = false;
317
+ settings.initialCheck = true;
318
+ settings.refreshOnLoad = true;
319
+ if (!parameters.transition) {
320
+ settings.transition = false;
321
+ }
322
+ module.create.placeholder();
323
+ module.debug('Added placeholder', $placeholder);
324
+ settings.onTopPassed = function () {
325
+ module.debug('Element passed, adding fixed position', $module);
326
+ module.show.placeholder();
327
+ module.set.fixed();
328
+ if (settings.transition) {
329
+ if ($.fn.transition !== undefined) {
330
+ $module.transition(settings.transition, settings.duration);
331
+ }
332
+ }
333
+ };
334
+ settings.onTopPassedReverse = function () {
335
+ module.debug('Element returned to position, removing fixed', $module);
336
+ module.hide.placeholder();
337
+ module.remove.fixed();
338
+ };
339
+ },
340
+ },
341
+
342
+ create: {
343
+ placeholder: function () {
344
+ module.verbose('Creating fixed position placeholder');
345
+ $placeholder = $module
346
+ .clone(false)
347
+ .css('display', 'none')
348
+ .addClass(className.placeholder)
349
+ .insertAfter($module)
350
+ ;
351
+ },
352
+ },
353
+
354
+ show: {
355
+ placeholder: function () {
356
+ module.verbose('Showing placeholder');
357
+ $placeholder
358
+ .css('display', 'block')
359
+ .css('visibility', 'hidden')
360
+ ;
361
+ },
362
+ },
363
+ hide: {
364
+ placeholder: function () {
365
+ module.verbose('Hiding placeholder');
366
+ $placeholder
367
+ .css('display', 'none')
368
+ .css('visibility', '')
369
+ ;
370
+ },
371
+ },
372
+
373
+ set: {
374
+ fixed: function () {
375
+ module.verbose('Setting element to fixed position');
376
+ $module
377
+ .addClass(className.fixed)
378
+ .css({
379
+ position: 'fixed',
380
+ top: settings.offset + 'px',
381
+ left: 'auto',
382
+ zIndex: settings.zIndex,
383
+ })
384
+ ;
385
+ settings.onFixed.call(element);
386
+ },
387
+ image: function (src, callback) {
388
+ $module
389
+ .attr('src', src)
390
+ ;
391
+ if (settings.transition) {
392
+ if ($.fn.transition !== undefined) {
393
+ if ($module.hasClass(className.visible)) {
394
+ module.debug('Transition already occurred on this image, skipping animation');
395
+
396
+ return;
397
+ }
398
+ $module.transition(settings.transition, settings.duration, callback);
399
+ } else {
400
+ $module.fadeIn(settings.duration, callback);
401
+ }
402
+ } else {
403
+ $module.show();
404
+ }
405
+ },
406
+ },
407
+
408
+ is: {
409
+ onScreen: function () {
410
+ var
411
+ calculations = module.get.elementCalculations()
412
+ ;
413
+
414
+ return calculations.onScreen;
415
+ },
416
+ offScreen: function () {
417
+ var
418
+ calculations = module.get.elementCalculations()
419
+ ;
420
+
421
+ return calculations.offScreen;
422
+ },
423
+ visible: function () {
424
+ if (module.cache && module.cache.element) {
425
+ return !(module.cache.element.width === 0 && module.cache.element.offset.top === 0);
426
+ }
427
+
428
+ return false;
429
+ },
430
+ verticallyScrollableContext: function () {
431
+ var
432
+ overflowY = ($context[0] !== window)
433
+ ? $context.css('overflow-y')
434
+ : false
435
+ ;
436
+
437
+ return (overflowY == 'auto' || overflowY == 'scroll');
438
+ },
439
+ horizontallyScrollableContext: function () {
440
+ var
441
+ overflowX = ($context[0] !== window)
442
+ ? $context.css('overflow-x')
443
+ : false
444
+ ;
445
+
446
+ return (overflowX == 'auto' || overflowX == 'scroll');
447
+ },
448
+ },
449
+
450
+ refresh: function () {
451
+ module.debug('Refreshing constants (width/height)');
452
+ if (settings.type == 'fixed') {
453
+ module.resetFixed();
454
+ }
455
+ module.reset();
456
+ module.save.position();
457
+ if (settings.checkOnRefresh) {
458
+ module.checkVisibility();
459
+ }
460
+ settings.onRefresh.call(element);
461
+ },
462
+
463
+ resetFixed: function () {
464
+ module.remove.fixed();
465
+ module.remove.occurred();
466
+ },
467
+
468
+ reset: function () {
469
+ module.verbose('Resetting all cached values');
470
+ if ($.isPlainObject(module.cache)) {
471
+ module.cache.screen = {};
472
+ module.cache.element = {};
473
+ }
474
+ },
475
+
476
+ checkVisibility: function (scroll) {
477
+ module.verbose('Checking visibility of element', module.cache.element);
478
+
479
+ if (!disabled && module.is.visible()) {
480
+ // save scroll position
481
+ module.save.scroll(scroll);
482
+
483
+ // update calculations derived from scroll
484
+ module.save.calculations();
485
+
486
+ // percentage
487
+ module.passed();
488
+
489
+ // reverse (must be first)
490
+ module.passingReverse();
491
+ module.topVisibleReverse();
492
+ module.bottomVisibleReverse();
493
+ module.topPassedReverse();
494
+ module.bottomPassedReverse();
495
+
496
+ // one time
497
+ module.onScreen();
498
+ module.offScreen();
499
+ module.passing();
500
+ module.topVisible();
501
+ module.bottomVisible();
502
+ module.topPassed();
503
+ module.bottomPassed();
504
+
505
+ // on update callback
506
+ if (settings.onUpdate) {
507
+ settings.onUpdate.call(element, module.get.elementCalculations());
508
+ }
509
+ }
510
+ },
511
+
512
+ passed: function (amount, newCallback) {
513
+ var
514
+ calculations = module.get.elementCalculations()
515
+ ;
516
+ // assign callback
517
+ if (amount && newCallback) {
518
+ settings.onPassed[amount] = newCallback;
519
+ } else if (amount !== undefined) {
520
+ return (module.get.pixelsPassed(amount) > calculations.pixelsPassed);
521
+ } else if (calculations.passing) {
522
+ $.each(settings.onPassed, function (amount, callback) {
523
+ if (calculations.bottomVisible || calculations.pixelsPassed > module.get.pixelsPassed(amount)) {
524
+ module.execute(callback, amount);
525
+ } else if (!settings.once) {
526
+ module.remove.occurred(callback);
527
+ }
528
+ });
529
+ }
530
+ },
531
+
532
+ onScreen: function (newCallback) {
533
+ var
534
+ calculations = module.get.elementCalculations(),
535
+ callback = newCallback || settings.onOnScreen,
536
+ callbackName = 'onScreen'
537
+ ;
538
+ if (newCallback) {
539
+ module.debug('Adding callback for onScreen', newCallback);
540
+ settings.onOnScreen = newCallback;
541
+ }
542
+ if (calculations.onScreen) {
543
+ module.execute(callback, callbackName);
544
+ } else if (!settings.once) {
545
+ module.remove.occurred(callbackName);
546
+ }
547
+ if (newCallback !== undefined) {
548
+ return calculations.onOnScreen;
549
+ }
550
+ },
551
+
552
+ offScreen: function (newCallback) {
553
+ var
554
+ calculations = module.get.elementCalculations(),
555
+ callback = newCallback || settings.onOffScreen,
556
+ callbackName = 'offScreen'
557
+ ;
558
+ if (newCallback) {
559
+ module.debug('Adding callback for offScreen', newCallback);
560
+ settings.onOffScreen = newCallback;
561
+ }
562
+ if (calculations.offScreen) {
563
+ module.execute(callback, callbackName);
564
+ } else if (!settings.once) {
565
+ module.remove.occurred(callbackName);
566
+ }
567
+ if (newCallback !== undefined) {
568
+ return calculations.onOffScreen;
569
+ }
570
+ },
571
+
572
+ passing: function (newCallback) {
573
+ var
574
+ calculations = module.get.elementCalculations(),
575
+ callback = newCallback || settings.onPassing,
576
+ callbackName = 'passing'
577
+ ;
578
+ if (newCallback) {
579
+ module.debug('Adding callback for passing', newCallback);
580
+ settings.onPassing = newCallback;
581
+ }
582
+ if (calculations.passing) {
583
+ module.execute(callback, callbackName);
584
+ } else if (!settings.once) {
585
+ module.remove.occurred(callbackName);
586
+ }
587
+ if (newCallback !== undefined) {
588
+ return calculations.passing;
589
+ }
590
+ },
591
+
592
+ topVisible: function (newCallback) {
593
+ var
594
+ calculations = module.get.elementCalculations(),
595
+ callback = newCallback || settings.onTopVisible,
596
+ callbackName = 'topVisible'
597
+ ;
598
+ if (newCallback) {
599
+ module.debug('Adding callback for top visible', newCallback);
600
+ settings.onTopVisible = newCallback;
601
+ }
602
+ if (calculations.topVisible) {
603
+ module.execute(callback, callbackName);
604
+ } else if (!settings.once) {
605
+ module.remove.occurred(callbackName);
606
+ }
607
+ if (newCallback === undefined) {
608
+ return calculations.topVisible;
609
+ }
610
+ },
611
+
612
+ bottomVisible: function (newCallback) {
613
+ var
614
+ calculations = module.get.elementCalculations(),
615
+ callback = newCallback || settings.onBottomVisible,
616
+ callbackName = 'bottomVisible'
617
+ ;
618
+ if (newCallback) {
619
+ module.debug('Adding callback for bottom visible', newCallback);
620
+ settings.onBottomVisible = newCallback;
621
+ }
622
+ if (calculations.bottomVisible) {
623
+ module.execute(callback, callbackName);
624
+ } else if (!settings.once) {
625
+ module.remove.occurred(callbackName);
626
+ }
627
+ if (newCallback === undefined) {
628
+ return calculations.bottomVisible;
629
+ }
630
+ },
631
+
632
+ topPassed: function (newCallback) {
633
+ var
634
+ calculations = module.get.elementCalculations(),
635
+ callback = newCallback || settings.onTopPassed,
636
+ callbackName = 'topPassed'
637
+ ;
638
+ if (newCallback) {
639
+ module.debug('Adding callback for top passed', newCallback);
640
+ settings.onTopPassed = newCallback;
641
+ }
642
+ if (calculations.topPassed) {
643
+ module.execute(callback, callbackName);
644
+ } else if (!settings.once) {
645
+ module.remove.occurred(callbackName);
646
+ }
647
+ if (newCallback === undefined) {
648
+ return calculations.topPassed;
649
+ }
650
+ },
651
+
652
+ bottomPassed: function (newCallback) {
653
+ var
654
+ calculations = module.get.elementCalculations(),
655
+ callback = newCallback || settings.onBottomPassed,
656
+ callbackName = 'bottomPassed'
657
+ ;
658
+ if (newCallback) {
659
+ module.debug('Adding callback for bottom passed', newCallback);
660
+ settings.onBottomPassed = newCallback;
661
+ }
662
+ if (calculations.bottomPassed) {
663
+ module.execute(callback, callbackName);
664
+ } else if (!settings.once) {
665
+ module.remove.occurred(callbackName);
666
+ }
667
+ if (newCallback === undefined) {
668
+ return calculations.bottomPassed;
669
+ }
670
+ },
671
+
672
+ passingReverse: function (newCallback) {
673
+ var
674
+ calculations = module.get.elementCalculations(),
675
+ callback = newCallback || settings.onPassingReverse,
676
+ callbackName = 'passingReverse'
677
+ ;
678
+ if (newCallback) {
679
+ module.debug('Adding callback for passing reverse', newCallback);
680
+ settings.onPassingReverse = newCallback;
681
+ }
682
+ if (!calculations.passing) {
683
+ if (module.get.occurred('passing')) {
684
+ module.execute(callback, callbackName);
685
+ }
686
+ } else if (!settings.once) {
687
+ module.remove.occurred(callbackName);
688
+ }
689
+ if (newCallback !== undefined) {
690
+ return !calculations.passing;
691
+ }
692
+ },
693
+
694
+ topVisibleReverse: function (newCallback) {
695
+ var
696
+ calculations = module.get.elementCalculations(),
697
+ callback = newCallback || settings.onTopVisibleReverse,
698
+ callbackName = 'topVisibleReverse'
699
+ ;
700
+ if (newCallback) {
701
+ module.debug('Adding callback for top visible reverse', newCallback);
702
+ settings.onTopVisibleReverse = newCallback;
703
+ }
704
+ if (!calculations.topVisible) {
705
+ if (module.get.occurred('topVisible')) {
706
+ module.execute(callback, callbackName);
707
+ }
708
+ } else if (!settings.once) {
709
+ module.remove.occurred(callbackName);
710
+ }
711
+ if (newCallback === undefined) {
712
+ return !calculations.topVisible;
713
+ }
714
+ },
715
+
716
+ bottomVisibleReverse: function (newCallback) {
717
+ var
718
+ calculations = module.get.elementCalculations(),
719
+ callback = newCallback || settings.onBottomVisibleReverse,
720
+ callbackName = 'bottomVisibleReverse'
721
+ ;
722
+ if (newCallback) {
723
+ module.debug('Adding callback for bottom visible reverse', newCallback);
724
+ settings.onBottomVisibleReverse = newCallback;
725
+ }
726
+ if (!calculations.bottomVisible) {
727
+ if (module.get.occurred('bottomVisible')) {
728
+ module.execute(callback, callbackName);
729
+ }
730
+ } else if (!settings.once) {
731
+ module.remove.occurred(callbackName);
732
+ }
733
+ if (newCallback === undefined) {
734
+ return !calculations.bottomVisible;
735
+ }
736
+ },
737
+
738
+ topPassedReverse: function (newCallback) {
739
+ var
740
+ calculations = module.get.elementCalculations(),
741
+ callback = newCallback || settings.onTopPassedReverse,
742
+ callbackName = 'topPassedReverse'
743
+ ;
744
+ if (newCallback) {
745
+ module.debug('Adding callback for top passed reverse', newCallback);
746
+ settings.onTopPassedReverse = newCallback;
747
+ }
748
+ if (!calculations.topPassed) {
749
+ if (module.get.occurred('topPassed')) {
750
+ module.execute(callback, callbackName);
751
+ }
752
+ } else if (!settings.once) {
753
+ module.remove.occurred(callbackName);
754
+ }
755
+ if (newCallback === undefined) {
756
+ return !calculations.onTopPassed;
757
+ }
758
+ },
759
+
760
+ bottomPassedReverse: function (newCallback) {
761
+ var
762
+ calculations = module.get.elementCalculations(),
763
+ callback = newCallback || settings.onBottomPassedReverse,
764
+ callbackName = 'bottomPassedReverse'
765
+ ;
766
+ if (newCallback) {
767
+ module.debug('Adding callback for bottom passed reverse', newCallback);
768
+ settings.onBottomPassedReverse = newCallback;
769
+ }
770
+ if (!calculations.bottomPassed) {
771
+ if (module.get.occurred('bottomPassed')) {
772
+ module.execute(callback, callbackName);
773
+ }
774
+ } else if (!settings.once) {
775
+ module.remove.occurred(callbackName);
776
+ }
777
+ if (newCallback === undefined) {
778
+ return !calculations.bottomPassed;
779
+ }
780
+ },
781
+
782
+ execute: function (callback, callbackName) {
783
+ var
784
+ calculations = module.get.elementCalculations(),
785
+ screen = module.get.screenCalculations()
786
+ ;
787
+ callback = callback || false;
788
+ if (callback) {
789
+ if (settings.continuous) {
790
+ module.debug('Callback being called continuously', callbackName, calculations);
791
+ callback.call(element, calculations, screen);
792
+ } else if (!module.get.occurred(callbackName)) {
793
+ module.debug('Conditions met', callbackName, calculations);
794
+ callback.call(element, calculations, screen);
795
+ }
796
+ }
797
+ module.save.occurred(callbackName);
798
+ },
799
+
800
+ remove: {
801
+ fixed: function () {
802
+ module.debug('Removing fixed position');
803
+ $module
804
+ .removeClass(className.fixed)
805
+ .css({
806
+ position: '',
807
+ top: '',
808
+ left: '',
809
+ zIndex: '',
810
+ })
811
+ ;
812
+ settings.onUnfixed.call(element);
813
+ },
814
+ placeholder: function () {
815
+ module.debug('Removing placeholder content');
816
+ if ($placeholder) {
817
+ $placeholder.remove();
818
+ }
819
+ },
820
+ occurred: function (callback) {
821
+ if (callback) {
822
+ var
823
+ occurred = module.cache.occurred
824
+ ;
825
+ if (occurred[callback] !== undefined && occurred[callback] === true) {
826
+ module.debug('Callback can now be called again', callback);
827
+ module.cache.occurred[callback] = false;
828
+ }
829
+ } else {
830
+ module.cache.occurred = {};
831
+ }
832
+ },
833
+ },
834
+
835
+ save: {
836
+ calculations: function () {
837
+ module.verbose('Saving all calculations necessary to determine positioning');
838
+ module.save.direction();
839
+ module.save.screenCalculations();
840
+ module.save.elementCalculations();
841
+ },
842
+ occurred: function (callback) {
843
+ if (callback) {
844
+ if (module.cache.occurred[callback] === undefined || (module.cache.occurred[callback] !== true)) {
845
+ module.verbose('Saving callback occurred', callback);
846
+ module.cache.occurred[callback] = true;
847
+ }
848
+ }
849
+ },
850
+ scroll: function (scrollPosition) {
851
+ scrollPosition = scrollPosition + settings.offset || $context.scrollTop() + settings.offset;
852
+ module.cache.scroll = scrollPosition;
853
+ },
854
+ direction: function () {
855
+ var
856
+ scroll = module.get.scroll(),
857
+ lastScroll = module.get.lastScroll(),
858
+ direction
859
+ ;
860
+ if (scroll > lastScroll && lastScroll) {
861
+ direction = 'down';
862
+ } else if (scroll < lastScroll && lastScroll) {
863
+ direction = 'up';
864
+ } else {
865
+ direction = 'static';
866
+ }
867
+ module.cache.direction = direction;
868
+
869
+ return module.cache.direction;
870
+ },
871
+ elementPosition: function () {
872
+ var
873
+ element = module.cache.element,
874
+ screen = module.get.screenSize()
875
+ ;
876
+ module.verbose('Saving element position');
877
+ // (quicker than $.extend)
878
+ element.fits = (element.height < screen.height);
879
+ element.offset = $module.offset();
880
+ element.width = $module.outerWidth();
881
+ element.height = $module.outerHeight();
882
+ // compensate for scroll in context
883
+ if (module.is.verticallyScrollableContext()) {
884
+ element.offset.top += $context.scrollTop() - $context.offset().top;
885
+ }
886
+ if (module.is.horizontallyScrollableContext()) {
887
+ element.offset.left += $context.scrollLeft() - $context.offset().left;
888
+ }
889
+ // store
890
+ module.cache.element = element;
891
+
892
+ return element;
893
+ },
894
+ elementCalculations: function () {
895
+ var
896
+ screen = module.get.screenCalculations(),
897
+ element = module.get.elementPosition()
898
+ ;
899
+ // offset
900
+ if (settings.includeMargin) {
901
+ element.margin = {};
902
+ element.margin.top = parseInt($module.css('margin-top'), 10);
903
+ element.margin.bottom = parseInt($module.css('margin-bottom'), 10);
904
+ element.top = element.offset.top - element.margin.top;
905
+ element.bottom = element.offset.top + element.height + element.margin.bottom;
906
+ } else {
907
+ element.top = element.offset.top;
908
+ element.bottom = element.offset.top + element.height;
909
+ }
910
+
911
+ // visibility
912
+ element.topPassed = (screen.top >= element.top);
913
+ element.bottomPassed = (screen.top >= element.bottom);
914
+ element.topVisible = (screen.bottom >= element.top) && !element.topPassed;
915
+ element.bottomVisible = (screen.bottom >= element.bottom) && !element.bottomPassed;
916
+ element.pixelsPassed = 0;
917
+ element.percentagePassed = 0;
918
+
919
+ // meta calculations
920
+ element.onScreen = ((element.topVisible || element.passing) && !element.bottomPassed);
921
+ element.passing = (element.topPassed && !element.bottomPassed);
922
+ element.offScreen = (!element.onScreen);
923
+
924
+ // passing calculations
925
+ if (element.passing) {
926
+ element.pixelsPassed = (screen.top - element.top);
927
+ element.percentagePassed = (screen.top - element.top) / element.height;
928
+ }
929
+ module.cache.element = element;
930
+ module.verbose('Updated element calculations', element);
931
+
932
+ return element;
933
+ },
934
+ screenCalculations: function () {
935
+ var
936
+ scroll = module.get.scroll()
937
+ ;
938
+ module.save.direction();
939
+ module.cache.screen.top = scroll;
940
+ module.cache.screen.bottom = scroll + module.cache.screen.height;
941
+
942
+ return module.cache.screen;
943
+ },
944
+ screenSize: function () {
945
+ module.verbose('Saving window position');
946
+ module.cache.screen = {
947
+ height: $context.height(),
948
+ };
949
+ },
950
+ position: function () {
951
+ module.save.screenSize();
952
+ module.save.elementPosition();
953
+ },
954
+ },
955
+
956
+ get: {
957
+ pixelsPassed: function (amount) {
958
+ var
959
+ element = module.get.elementCalculations()
960
+ ;
961
+ if (amount.search('%') > -1) {
962
+ return (element.height * (parseInt(amount, 10) / 100));
963
+ }
964
+
965
+ return parseInt(amount, 10);
966
+ },
967
+ occurred: function (callback) {
968
+ return (module.cache.occurred !== undefined)
969
+ ? module.cache.occurred[callback] || false
970
+ : false;
971
+ },
972
+ direction: function () {
973
+ if (module.cache.direction === undefined) {
974
+ module.save.direction();
975
+ }
976
+
977
+ return module.cache.direction;
978
+ },
979
+ elementPosition: function () {
980
+ if (module.cache.element === undefined) {
981
+ module.save.elementPosition();
982
+ }
983
+
984
+ return module.cache.element;
985
+ },
986
+ elementCalculations: function () {
987
+ if (module.cache.element === undefined) {
988
+ module.save.elementCalculations();
989
+ }
990
+
991
+ return module.cache.element;
992
+ },
993
+ screenCalculations: function () {
994
+ if (module.cache.screen === undefined) {
995
+ module.save.screenCalculations();
996
+ }
997
+
998
+ return module.cache.screen;
999
+ },
1000
+ screenSize: function () {
1001
+ if (module.cache.screen === undefined) {
1002
+ module.save.screenSize();
1003
+ }
1004
+
1005
+ return module.cache.screen;
1006
+ },
1007
+ scroll: function () {
1008
+ if (module.cache.scroll === undefined) {
1009
+ module.save.scroll();
1010
+ }
1011
+
1012
+ return module.cache.scroll;
1013
+ },
1014
+ lastScroll: function () {
1015
+ if (module.cache.screen === undefined) {
1016
+ module.debug('First scroll event, no last scroll could be found');
1017
+
1018
+ return false;
1019
+ }
1020
+
1021
+ return module.cache.screen.top;
1022
+ },
1023
+ },
1024
+
1025
+ setting: function (name, value) {
1026
+ if ($.isPlainObject(name)) {
1027
+ $.extend(true, settings, name);
1028
+ } else if (value !== undefined) {
1029
+ settings[name] = value;
1030
+ } else {
1031
+ return settings[name];
1032
+ }
1033
+ },
1034
+ internal: function (name, value) {
1035
+ if ($.isPlainObject(name)) {
1036
+ $.extend(true, module, name);
1037
+ } else if (value !== undefined) {
1038
+ module[name] = value;
1039
+ } else {
1040
+ return module[name];
1041
+ }
1042
+ },
1043
+ debug: function () {
1044
+ if (!settings.silent && settings.debug) {
1045
+ if (settings.performance) {
1046
+ module.performance.log(arguments);
1047
+ } else {
1048
+ module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
1049
+ module.debug.apply(console, arguments);
1050
+ }
1051
+ }
1052
+ },
1053
+ verbose: function () {
1054
+ if (!settings.silent && settings.verbose && settings.debug) {
1055
+ if (settings.performance) {
1056
+ module.performance.log(arguments);
1057
+ } else {
1058
+ module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
1059
+ module.verbose.apply(console, arguments);
1060
+ }
1061
+ }
1062
+ },
1063
+ error: function () {
1064
+ if (!settings.silent) {
1065
+ module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
1066
+ module.error.apply(console, arguments);
1067
+ }
1068
+ },
1069
+ performance: {
1070
+ log: function (message) {
1071
+ var
1072
+ currentTime,
1073
+ executionTime,
1074
+ previousTime
1075
+ ;
1076
+ if (settings.performance) {
1077
+ currentTime = new Date().getTime();
1078
+ previousTime = time || currentTime;
1079
+ executionTime = currentTime - previousTime;
1080
+ time = currentTime;
1081
+ performance.push({
1082
+ Name: message[0],
1083
+ Arguments: [].slice.call(message, 1) || '',
1084
+ Element: element,
1085
+ 'Execution Time': executionTime,
1086
+ });
1087
+ }
1088
+ clearTimeout(module.performance.timer);
1089
+ module.performance.timer = setTimeout(module.performance.display, 500);
1090
+ },
1091
+ display: function () {
1092
+ var
1093
+ title = settings.name + ':',
1094
+ totalTime = 0
1095
+ ;
1096
+ time = false;
1097
+ clearTimeout(module.performance.timer);
1098
+ $.each(performance, function (index, data) {
1099
+ totalTime += data['Execution Time'];
1100
+ });
1101
+ title += ' ' + totalTime + 'ms';
1102
+ if (moduleSelector) {
1103
+ title += ' \'' + moduleSelector + '\'';
1104
+ }
1105
+ if ((console.group !== undefined || console.table !== undefined) && performance.length > 0) {
1106
+ console.groupCollapsed(title);
1107
+ if (console.table) {
1108
+ console.table(performance);
1109
+ } else {
1110
+ $.each(performance, function (index, data) {
1111
+ console.log(data.Name + ': ' + data['Execution Time'] + 'ms');
1112
+ });
1113
+ }
1114
+ console.groupEnd();
1115
+ }
1116
+ performance = [];
1117
+ },
1118
+ },
1119
+ invoke: function (query, passedArguments, context) {
1120
+ var
1121
+ object = instance,
1122
+ maxDepth,
1123
+ found,
1124
+ response
1125
+ ;
1126
+ passedArguments = passedArguments || queryArguments;
1127
+ context = context || element;
1128
+ if (typeof query == 'string' && object !== undefined) {
1129
+ query = query.split(/[\. ]/);
1130
+ maxDepth = query.length - 1;
1131
+ $.each(query, function (depth, value) {
1132
+ var camelCaseValue = (depth != maxDepth)
1133
+ ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
1134
+ : query
1135
+ ;
1136
+ if ($.isPlainObject(object[camelCaseValue]) && (depth != maxDepth)) {
1137
+ object = object[camelCaseValue];
1138
+ } else if (object[camelCaseValue] !== undefined) {
1139
+ found = object[camelCaseValue];
1140
+
1141
+ return false;
1142
+ } else if ($.isPlainObject(object[value]) && (depth != maxDepth)) {
1143
+ object = object[value];
1144
+ } else if (object[value] !== undefined) {
1145
+ found = object[value];
1146
+
1147
+ return false;
1148
+ } else {
1149
+ module.error(error.method, query);
1150
+
1151
+ return false;
1152
+ }
1153
+ });
1154
+ }
1155
+ if (isFunction(found)) {
1156
+ response = found.apply(context, passedArguments);
1157
+ } else if (found !== undefined) {
1158
+ response = found;
1159
+ }
1160
+ if (Array.isArray(returnedValue)) {
1161
+ returnedValue.push(response);
1162
+ } else if (returnedValue !== undefined) {
1163
+ returnedValue = [returnedValue, response];
1164
+ } else if (response !== undefined) {
1165
+ returnedValue = response;
1166
+ }
354
1167
 
355
- show: {
356
- placeholder: function() {
357
- module.verbose('Showing placeholder');
358
- $placeholder
359
- .css('display', 'block')
360
- .css('visibility', 'hidden')
361
- ;
362
- }
363
- },
364
- hide: {
365
- placeholder: function() {
366
- module.verbose('Hiding placeholder');
367
- $placeholder
368
- .css('display', 'none')
369
- .css('visibility', '')
370
- ;
371
- }
372
- },
1168
+ return found;
1169
+ },
1170
+ };
373
1171
 
374
- set: {
375
- fixed: function() {
376
- module.verbose('Setting element to fixed position');
377
- $module
378
- .addClass(className.fixed)
379
- .css({
380
- position : 'fixed',
381
- top : settings.offset + 'px',
382
- left : 'auto',
383
- zIndex : settings.zIndex
384
- })
385
- ;
386
- settings.onFixed.call(element);
387
- },
388
- image: function(src, callback) {
389
- $module
390
- .attr('src', src)
391
- ;
392
- if(settings.transition) {
393
- if( $.fn.transition !== undefined) {
394
- if($module.hasClass(className.visible)) {
395
- module.debug('Transition already occurred on this image, skipping animation');
396
- return;
1172
+ if (methodInvoked) {
1173
+ if (instance === undefined) {
1174
+ module.initialize();
397
1175
  }
398
- $module.transition(settings.transition, settings.duration, callback);
399
- }
400
- else {
401
- $module.fadeIn(settings.duration, callback);
402
- }
403
- }
404
- else {
405
- $module.show();
406
- }
407
- }
408
- },
409
-
410
- is: {
411
- onScreen: function() {
412
- var
413
- calculations = module.get.elementCalculations()
414
- ;
415
- return calculations.onScreen;
416
- },
417
- offScreen: function() {
418
- var
419
- calculations = module.get.elementCalculations()
420
- ;
421
- return calculations.offScreen;
422
- },
423
- visible: function() {
424
- if(module.cache && module.cache.element) {
425
- return !(module.cache.element.width === 0 && module.cache.element.offset.top === 0);
1176
+ instance.save.scroll();
1177
+ instance.save.calculations();
1178
+ module.invoke(query);
1179
+ } else {
1180
+ if (instance !== undefined) {
1181
+ instance.invoke('destroy');
1182
+ }
1183
+ module.initialize();
426
1184
  }
427
- return false;
428
- },
429
- verticallyScrollableContext: function() {
430
- var
431
- overflowY = ($context[0] !== window)
432
- ? $context.css('overflow-y')
433
- : false
434
- ;
435
- return (overflowY == 'auto' || overflowY == 'scroll');
436
- },
437
- horizontallyScrollableContext: function() {
438
- var
439
- overflowX = ($context[0] !== window)
440
- ? $context.css('overflow-x')
441
- : false
442
- ;
443
- return (overflowX == 'auto' || overflowX == 'scroll');
444
- }
445
- },
446
-
447
- refresh: function() {
448
- module.debug('Refreshing constants (width/height)');
449
- if(settings.type == 'fixed') {
450
- module.resetFixed();
451
- }
452
- module.reset();
453
- module.save.position();
454
- if(settings.checkOnRefresh) {
455
- module.checkVisibility();
456
- }
457
- settings.onRefresh.call(element);
458
- },
459
-
460
- resetFixed: function () {
461
- module.remove.fixed();
462
- module.remove.occurred();
463
- },
464
-
465
- reset: function() {
466
- module.verbose('Resetting all cached values');
467
- if( $.isPlainObject(module.cache) ) {
468
- module.cache.screen = {};
469
- module.cache.element = {};
470
- }
471
- },
472
-
473
- checkVisibility: function(scroll) {
474
- module.verbose('Checking visibility of element', module.cache.element);
1185
+ });
475
1186
 
476
- if( !disabled && module.is.visible() ) {
1187
+ return (returnedValue !== undefined)
1188
+ ? returnedValue
1189
+ : this;
1190
+ };
477
1191
 
478
- // save scroll position
479
- module.save.scroll(scroll);
1192
+ $.fn.visibility.settings = {
480
1193
 
481
- // update calculations derived from scroll
482
- module.save.calculations();
1194
+ name: 'Visibility',
1195
+ namespace: 'visibility',
483
1196
 
484
- // percentage
485
- module.passed();
1197
+ debug: false,
1198
+ verbose: false,
1199
+ performance: true,
486
1200
 
487
- // reverse (must be first)
488
- module.passingReverse();
489
- module.topVisibleReverse();
490
- module.bottomVisibleReverse();
491
- module.topPassedReverse();
492
- module.bottomPassedReverse();
1201
+ // whether to use mutation observers to follow changes
1202
+ observeChanges: true,
493
1203
 
494
- // one time
495
- module.onScreen();
496
- module.offScreen();
497
- module.passing();
498
- module.topVisible();
499
- module.bottomVisible();
500
- module.topPassed();
501
- module.bottomPassed();
1204
+ // check position immediately on init
1205
+ initialCheck: true,
502
1206
 
503
- // on update callback
504
- if(settings.onUpdate) {
505
- settings.onUpdate.call(element, module.get.elementCalculations());
506
- }
507
- }
508
- },
1207
+ // whether to refresh calculations after all page images load
1208
+ refreshOnLoad: true,
509
1209
 
510
- passed: function(amount, newCallback) {
511
- var
512
- calculations = module.get.elementCalculations()
513
- ;
514
- // assign callback
515
- if(amount && newCallback) {
516
- settings.onPassed[amount] = newCallback;
517
- }
518
- else if(amount !== undefined) {
519
- return (module.get.pixelsPassed(amount) > calculations.pixelsPassed);
520
- }
521
- else if(calculations.passing) {
522
- $.each(settings.onPassed, function(amount, callback) {
523
- if(calculations.bottomVisible || calculations.pixelsPassed > module.get.pixelsPassed(amount)) {
524
- module.execute(callback, amount);
525
- }
526
- else if(!settings.once) {
527
- module.remove.occurred(callback);
528
- }
529
- });
530
- }
531
- },
1210
+ // whether to refresh calculations after page resize event
1211
+ refreshOnResize: true,
532
1212
 
533
- onScreen: function(newCallback) {
534
- var
535
- calculations = module.get.elementCalculations(),
536
- callback = newCallback || settings.onOnScreen,
537
- callbackName = 'onScreen'
538
- ;
539
- if(newCallback) {
540
- module.debug('Adding callback for onScreen', newCallback);
541
- settings.onOnScreen = newCallback;
542
- }
543
- if(calculations.onScreen) {
544
- module.execute(callback, callbackName);
545
- }
546
- else if(!settings.once) {
547
- module.remove.occurred(callbackName);
548
- }
549
- if(newCallback !== undefined) {
550
- return calculations.onOnScreen;
551
- }
552
- },
1213
+ // should call callbacks on refresh event (resize, etc)
1214
+ checkOnRefresh: true,
553
1215
 
554
- offScreen: function(newCallback) {
555
- var
556
- calculations = module.get.elementCalculations(),
557
- callback = newCallback || settings.onOffScreen,
558
- callbackName = 'offScreen'
559
- ;
560
- if(newCallback) {
561
- module.debug('Adding callback for offScreen', newCallback);
562
- settings.onOffScreen = newCallback;
563
- }
564
- if(calculations.offScreen) {
565
- module.execute(callback, callbackName);
566
- }
567
- else if(!settings.once) {
568
- module.remove.occurred(callbackName);
569
- }
570
- if(newCallback !== undefined) {
571
- return calculations.onOffScreen;
572
- }
573
- },
1216
+ // callback should only occur one time
1217
+ once: true,
574
1218
 
575
- passing: function(newCallback) {
576
- var
577
- calculations = module.get.elementCalculations(),
578
- callback = newCallback || settings.onPassing,
579
- callbackName = 'passing'
580
- ;
581
- if(newCallback) {
582
- module.debug('Adding callback for passing', newCallback);
583
- settings.onPassing = newCallback;
584
- }
585
- if(calculations.passing) {
586
- module.execute(callback, callbackName);
587
- }
588
- else if(!settings.once) {
589
- module.remove.occurred(callbackName);
590
- }
591
- if(newCallback !== undefined) {
592
- return calculations.passing;
593
- }
594
- },
1219
+ // callback should fire continuously when evaluates to true
1220
+ continuous: false,
595
1221
 
1222
+ // offset to use with scroll top
1223
+ offset: 0,
596
1224
 
597
- topVisible: function(newCallback) {
598
- var
599
- calculations = module.get.elementCalculations(),
600
- callback = newCallback || settings.onTopVisible,
601
- callbackName = 'topVisible'
602
- ;
603
- if(newCallback) {
604
- module.debug('Adding callback for top visible', newCallback);
605
- settings.onTopVisible = newCallback;
606
- }
607
- if(calculations.topVisible) {
608
- module.execute(callback, callbackName);
609
- }
610
- else if(!settings.once) {
611
- module.remove.occurred(callbackName);
612
- }
613
- if(newCallback === undefined) {
614
- return calculations.topVisible;
615
- }
616
- },
1225
+ // whether to include margin in elements position
1226
+ includeMargin: false,
617
1227
 
618
- bottomVisible: function(newCallback) {
619
- var
620
- calculations = module.get.elementCalculations(),
621
- callback = newCallback || settings.onBottomVisible,
622
- callbackName = 'bottomVisible'
623
- ;
624
- if(newCallback) {
625
- module.debug('Adding callback for bottom visible', newCallback);
626
- settings.onBottomVisible = newCallback;
627
- }
628
- if(calculations.bottomVisible) {
629
- module.execute(callback, callbackName);
630
- }
631
- else if(!settings.once) {
632
- module.remove.occurred(callbackName);
633
- }
634
- if(newCallback === undefined) {
635
- return calculations.bottomVisible;
636
- }
637
- },
638
-
639
- topPassed: function(newCallback) {
640
- var
641
- calculations = module.get.elementCalculations(),
642
- callback = newCallback || settings.onTopPassed,
643
- callbackName = 'topPassed'
644
- ;
645
- if(newCallback) {
646
- module.debug('Adding callback for top passed', newCallback);
647
- settings.onTopPassed = newCallback;
648
- }
649
- if(calculations.topPassed) {
650
- module.execute(callback, callbackName);
651
- }
652
- else if(!settings.once) {
653
- module.remove.occurred(callbackName);
654
- }
655
- if(newCallback === undefined) {
656
- return calculations.topPassed;
657
- }
658
- },
1228
+ // scroll context for visibility checks
1229
+ context: window,
659
1230
 
660
- bottomPassed: function(newCallback) {
661
- var
662
- calculations = module.get.elementCalculations(),
663
- callback = newCallback || settings.onBottomPassed,
664
- callbackName = 'bottomPassed'
665
- ;
666
- if(newCallback) {
667
- module.debug('Adding callback for bottom passed', newCallback);
668
- settings.onBottomPassed = newCallback;
669
- }
670
- if(calculations.bottomPassed) {
671
- module.execute(callback, callbackName);
672
- }
673
- else if(!settings.once) {
674
- module.remove.occurred(callbackName);
675
- }
676
- if(newCallback === undefined) {
677
- return calculations.bottomPassed;
678
- }
679
- },
1231
+ // visibility check delay in ms (defaults to animationFrame)
1232
+ throttle: false,
680
1233
 
681
- passingReverse: function(newCallback) {
682
- var
683
- calculations = module.get.elementCalculations(),
684
- callback = newCallback || settings.onPassingReverse,
685
- callbackName = 'passingReverse'
686
- ;
687
- if(newCallback) {
688
- module.debug('Adding callback for passing reverse', newCallback);
689
- settings.onPassingReverse = newCallback;
690
- }
691
- if(!calculations.passing) {
692
- if(module.get.occurred('passing')) {
693
- module.execute(callback, callbackName);
694
- }
695
- }
696
- else if(!settings.once) {
697
- module.remove.occurred(callbackName);
698
- }
699
- if(newCallback !== undefined) {
700
- return !calculations.passing;
701
- }
702
- },
1234
+ // special visibility type (image, fixed)
1235
+ type: false,
703
1236
 
1237
+ // z-index to use with visibility 'fixed'
1238
+ zIndex: '10',
704
1239
 
705
- topVisibleReverse: function(newCallback) {
706
- var
707
- calculations = module.get.elementCalculations(),
708
- callback = newCallback || settings.onTopVisibleReverse,
709
- callbackName = 'topVisibleReverse'
710
- ;
711
- if(newCallback) {
712
- module.debug('Adding callback for top visible reverse', newCallback);
713
- settings.onTopVisibleReverse = newCallback;
714
- }
715
- if(!calculations.topVisible) {
716
- if(module.get.occurred('topVisible')) {
717
- module.execute(callback, callbackName);
718
- }
719
- }
720
- else if(!settings.once) {
721
- module.remove.occurred(callbackName);
722
- }
723
- if(newCallback === undefined) {
724
- return !calculations.topVisible;
725
- }
726
- },
1240
+ // image only animation settings
1241
+ transition: 'fade in',
1242
+ duration: 1000,
727
1243
 
728
- bottomVisibleReverse: function(newCallback) {
729
- var
730
- calculations = module.get.elementCalculations(),
731
- callback = newCallback || settings.onBottomVisibleReverse,
732
- callbackName = 'bottomVisibleReverse'
733
- ;
734
- if(newCallback) {
735
- module.debug('Adding callback for bottom visible reverse', newCallback);
736
- settings.onBottomVisibleReverse = newCallback;
737
- }
738
- if(!calculations.bottomVisible) {
739
- if(module.get.occurred('bottomVisible')) {
740
- module.execute(callback, callbackName);
741
- }
742
- }
743
- else if(!settings.once) {
744
- module.remove.occurred(callbackName);
745
- }
746
- if(newCallback === undefined) {
747
- return !calculations.bottomVisible;
748
- }
749
- },
1244
+ // array of callbacks for percentage
1245
+ onPassed: {},
750
1246
 
751
- topPassedReverse: function(newCallback) {
752
- var
753
- calculations = module.get.elementCalculations(),
754
- callback = newCallback || settings.onTopPassedReverse,
755
- callbackName = 'topPassedReverse'
756
- ;
757
- if(newCallback) {
758
- module.debug('Adding callback for top passed reverse', newCallback);
759
- settings.onTopPassedReverse = newCallback;
760
- }
761
- if(!calculations.topPassed) {
762
- if(module.get.occurred('topPassed')) {
763
- module.execute(callback, callbackName);
764
- }
765
- }
766
- else if(!settings.once) {
767
- module.remove.occurred(callbackName);
768
- }
769
- if(newCallback === undefined) {
770
- return !calculations.onTopPassed;
771
- }
772
- },
1247
+ // standard callbacks
1248
+ onOnScreen: false,
1249
+ onOffScreen: false,
1250
+ onPassing: false,
1251
+ onTopVisible: false,
1252
+ onBottomVisible: false,
1253
+ onTopPassed: false,
1254
+ onBottomPassed: false,
773
1255
 
774
- bottomPassedReverse: function(newCallback) {
775
- var
776
- calculations = module.get.elementCalculations(),
777
- callback = newCallback || settings.onBottomPassedReverse,
778
- callbackName = 'bottomPassedReverse'
779
- ;
780
- if(newCallback) {
781
- module.debug('Adding callback for bottom passed reverse', newCallback);
782
- settings.onBottomPassedReverse = newCallback;
783
- }
784
- if(!calculations.bottomPassed) {
785
- if(module.get.occurred('bottomPassed')) {
786
- module.execute(callback, callbackName);
787
- }
788
- }
789
- else if(!settings.once) {
790
- module.remove.occurred(callbackName);
791
- }
792
- if(newCallback === undefined) {
793
- return !calculations.bottomPassed;
794
- }
795
- },
1256
+ // reverse callbacks
1257
+ onPassingReverse: false,
1258
+ onTopVisibleReverse: false,
1259
+ onBottomVisibleReverse: false,
1260
+ onTopPassedReverse: false,
1261
+ onBottomPassedReverse: false,
796
1262
 
797
- execute: function(callback, callbackName) {
798
- var
799
- calculations = module.get.elementCalculations(),
800
- screen = module.get.screenCalculations()
801
- ;
802
- callback = callback || false;
803
- if(callback) {
804
- if(settings.continuous) {
805
- module.debug('Callback being called continuously', callbackName, calculations);
806
- callback.call(element, calculations, screen);
807
- }
808
- else if(!module.get.occurred(callbackName)) {
809
- module.debug('Conditions met', callbackName, calculations);
810
- callback.call(element, calculations, screen);
811
- }
812
- }
813
- module.save.occurred(callbackName);
814
- },
1263
+ // special callbacks for image
1264
+ onLoad: function () {},
1265
+ onAllLoaded: function () {},
815
1266
 
816
- remove: {
817
- fixed: function() {
818
- module.debug('Removing fixed position');
819
- $module
820
- .removeClass(className.fixed)
821
- .css({
822
- position : '',
823
- top : '',
824
- left : '',
825
- zIndex : ''
826
- })
827
- ;
828
- settings.onUnfixed.call(element);
829
- },
830
- placeholder: function() {
831
- module.debug('Removing placeholder content');
832
- if($placeholder) {
833
- $placeholder.remove();
834
- }
835
- },
836
- occurred: function(callback) {
837
- if(callback) {
838
- var
839
- occurred = module.cache.occurred
840
- ;
841
- if(occurred[callback] !== undefined && occurred[callback] === true) {
842
- module.debug('Callback can now be called again', callback);
843
- module.cache.occurred[callback] = false;
844
- }
845
- }
846
- else {
847
- module.cache.occurred = {};
848
- }
849
- }
850
- },
1267
+ // special callbacks for fixed position
1268
+ onFixed: function () {},
1269
+ onUnfixed: function () {},
851
1270
 
852
- save: {
853
- calculations: function() {
854
- module.verbose('Saving all calculations necessary to determine positioning');
855
- module.save.direction();
856
- module.save.screenCalculations();
857
- module.save.elementCalculations();
858
- },
859
- occurred: function(callback) {
860
- if(callback) {
861
- if(module.cache.occurred[callback] === undefined || (module.cache.occurred[callback] !== true)) {
862
- module.verbose('Saving callback occurred', callback);
863
- module.cache.occurred[callback] = true;
864
- }
865
- }
866
- },
867
- scroll: function(scrollPosition) {
868
- scrollPosition = scrollPosition + settings.offset || $context.scrollTop() + settings.offset;
869
- module.cache.scroll = scrollPosition;
870
- },
871
- direction: function() {
872
- var
873
- scroll = module.get.scroll(),
874
- lastScroll = module.get.lastScroll(),
875
- direction
876
- ;
877
- if(scroll > lastScroll && lastScroll) {
878
- direction = 'down';
879
- }
880
- else if(scroll < lastScroll && lastScroll) {
881
- direction = 'up';
882
- }
883
- else {
884
- direction = 'static';
885
- }
886
- module.cache.direction = direction;
887
- return module.cache.direction;
888
- },
889
- elementPosition: function() {
890
- var
891
- element = module.cache.element,
892
- screen = module.get.screenSize()
893
- ;
894
- module.verbose('Saving element position');
895
- // (quicker than $.extend)
896
- element.fits = (element.height < screen.height);
897
- element.offset = $module.offset();
898
- element.width = $module.outerWidth();
899
- element.height = $module.outerHeight();
900
- // compensate for scroll in context
901
- if(module.is.verticallyScrollableContext()) {
902
- element.offset.top += $context.scrollTop() - $context.offset().top;
903
- }
904
- if(module.is.horizontallyScrollableContext()) {
905
- element.offset.left += $context.scrollLeft() - $context.offset().left;
906
- }
907
- // store
908
- module.cache.element = element;
909
- return element;
910
- },
911
- elementCalculations: function() {
912
- var
913
- screen = module.get.screenCalculations(),
914
- element = module.get.elementPosition()
915
- ;
916
- // offset
917
- if(settings.includeMargin) {
918
- element.margin = {};
919
- element.margin.top = parseInt($module.css('margin-top'), 10);
920
- element.margin.bottom = parseInt($module.css('margin-bottom'), 10);
921
- element.top = element.offset.top - element.margin.top;
922
- element.bottom = element.offset.top + element.height + element.margin.bottom;
923
- }
924
- else {
925
- element.top = element.offset.top;
926
- element.bottom = element.offset.top + element.height;
927
- }
1271
+ // utility callbacks
1272
+ onUpdate: false, // disabled by default for performance
1273
+ onRefresh: function () {},
928
1274
 
929
- // visibility
930
- element.topPassed = (screen.top >= element.top);
931
- element.bottomPassed = (screen.top >= element.bottom);
932
- element.topVisible = (screen.bottom >= element.top) && !element.topPassed;
933
- element.bottomVisible = (screen.bottom >= element.bottom) && !element.bottomPassed;
934
- element.pixelsPassed = 0;
935
- element.percentagePassed = 0;
936
-
937
- // meta calculations
938
- element.onScreen = ((element.topVisible || element.passing) && !element.bottomPassed);
939
- element.passing = (element.topPassed && !element.bottomPassed);
940
- element.offScreen = (!element.onScreen);
941
-
942
- // passing calculations
943
- if(element.passing) {
944
- element.pixelsPassed = (screen.top - element.top);
945
- element.percentagePassed = (screen.top - element.top) / element.height;
946
- }
947
- module.cache.element = element;
948
- module.verbose('Updated element calculations', element);
949
- return element;
950
- },
951
- screenCalculations: function() {
952
- var
953
- scroll = module.get.scroll()
954
- ;
955
- module.save.direction();
956
- module.cache.screen.top = scroll;
957
- module.cache.screen.bottom = scroll + module.cache.screen.height;
958
- return module.cache.screen;
959
- },
960
- screenSize: function() {
961
- module.verbose('Saving window position');
962
- module.cache.screen = {
963
- height: $context.height()
964
- };
965
- },
966
- position: function() {
967
- module.save.screenSize();
968
- module.save.elementPosition();
969
- }
1275
+ metadata: {
1276
+ src: 'src',
970
1277
  },
971
1278
 
972
- get: {
973
- pixelsPassed: function(amount) {
974
- var
975
- element = module.get.elementCalculations()
976
- ;
977
- if(amount.search('%') > -1) {
978
- return ( element.height * (parseInt(amount, 10) / 100) );
979
- }
980
- return parseInt(amount, 10);
981
- },
982
- occurred: function(callback) {
983
- return (module.cache.occurred !== undefined)
984
- ? module.cache.occurred[callback] || false
985
- : false
986
- ;
987
- },
988
- direction: function() {
989
- if(module.cache.direction === undefined) {
990
- module.save.direction();
991
- }
992
- return module.cache.direction;
993
- },
994
- elementPosition: function() {
995
- if(module.cache.element === undefined) {
996
- module.save.elementPosition();
997
- }
998
- return module.cache.element;
999
- },
1000
- elementCalculations: function() {
1001
- if(module.cache.element === undefined) {
1002
- module.save.elementCalculations();
1003
- }
1004
- return module.cache.element;
1005
- },
1006
- screenCalculations: function() {
1007
- if(module.cache.screen === undefined) {
1008
- module.save.screenCalculations();
1009
- }
1010
- return module.cache.screen;
1011
- },
1012
- screenSize: function() {
1013
- if(module.cache.screen === undefined) {
1014
- module.save.screenSize();
1015
- }
1016
- return module.cache.screen;
1017
- },
1018
- scroll: function() {
1019
- if(module.cache.scroll === undefined) {
1020
- module.save.scroll();
1021
- }
1022
- return module.cache.scroll;
1023
- },
1024
- lastScroll: function() {
1025
- if(module.cache.screen === undefined) {
1026
- module.debug('First scroll event, no last scroll could be found');
1027
- return false;
1028
- }
1029
- return module.cache.screen.top;
1030
- }
1279
+ className: {
1280
+ fixed: 'fixed',
1281
+ placeholder: 'constraint',
1282
+ visible: 'visible',
1031
1283
  },
1032
1284
 
1033
- setting: function(name, value) {
1034
- if( $.isPlainObject(name) ) {
1035
- $.extend(true, settings, name);
1036
- }
1037
- else if(value !== undefined) {
1038
- settings[name] = value;
1039
- }
1040
- else {
1041
- return settings[name];
1042
- }
1043
- },
1044
- internal: function(name, value) {
1045
- if( $.isPlainObject(name) ) {
1046
- $.extend(true, module, name);
1047
- }
1048
- else if(value !== undefined) {
1049
- module[name] = value;
1050
- }
1051
- else {
1052
- return module[name];
1053
- }
1054
- },
1055
- debug: function() {
1056
- if(!settings.silent && settings.debug) {
1057
- if(settings.performance) {
1058
- module.performance.log(arguments);
1059
- }
1060
- else {
1061
- module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
1062
- module.debug.apply(console, arguments);
1063
- }
1064
- }
1065
- },
1066
- verbose: function() {
1067
- if(!settings.silent && settings.verbose && settings.debug) {
1068
- if(settings.performance) {
1069
- module.performance.log(arguments);
1070
- }
1071
- else {
1072
- module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
1073
- module.verbose.apply(console, arguments);
1074
- }
1075
- }
1285
+ error: {
1286
+ method: 'The method you called is not defined.',
1287
+ visible: 'Element is hidden, you must call refresh after element becomes visible',
1076
1288
  },
1077
- error: function() {
1078
- if(!settings.silent) {
1079
- module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
1080
- module.error.apply(console, arguments);
1081
- }
1082
- },
1083
- performance: {
1084
- log: function(message) {
1085
- var
1086
- currentTime,
1087
- executionTime,
1088
- previousTime
1089
- ;
1090
- if(settings.performance) {
1091
- currentTime = new Date().getTime();
1092
- previousTime = time || currentTime;
1093
- executionTime = currentTime - previousTime;
1094
- time = currentTime;
1095
- performance.push({
1096
- 'Name' : message[0],
1097
- 'Arguments' : [].slice.call(message, 1) || '',
1098
- 'Element' : element,
1099
- 'Execution Time' : executionTime
1100
- });
1101
- }
1102
- clearTimeout(module.performance.timer);
1103
- module.performance.timer = setTimeout(module.performance.display, 500);
1104
- },
1105
- display: function() {
1106
- var
1107
- title = settings.name + ':',
1108
- totalTime = 0
1109
- ;
1110
- time = false;
1111
- clearTimeout(module.performance.timer);
1112
- $.each(performance, function(index, data) {
1113
- totalTime += data['Execution Time'];
1114
- });
1115
- title += ' ' + totalTime + 'ms';
1116
- if(moduleSelector) {
1117
- title += ' \'' + moduleSelector + '\'';
1118
- }
1119
- if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
1120
- console.groupCollapsed(title);
1121
- if(console.table) {
1122
- console.table(performance);
1123
- }
1124
- else {
1125
- $.each(performance, function(index, data) {
1126
- console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
1127
- });
1128
- }
1129
- console.groupEnd();
1130
- }
1131
- performance = [];
1132
- }
1133
- },
1134
- invoke: function(query, passedArguments, context) {
1135
- var
1136
- object = instance,
1137
- maxDepth,
1138
- found,
1139
- response
1140
- ;
1141
- passedArguments = passedArguments || queryArguments;
1142
- context = context || element;
1143
- if(typeof query == 'string' && object !== undefined) {
1144
- query = query.split(/[\. ]/);
1145
- maxDepth = query.length - 1;
1146
- $.each(query, function(depth, value) {
1147
- var camelCaseValue = (depth != maxDepth)
1148
- ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
1149
- : query
1150
- ;
1151
- if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
1152
- object = object[camelCaseValue];
1153
- }
1154
- else if( object[camelCaseValue] !== undefined ) {
1155
- found = object[camelCaseValue];
1156
- return false;
1157
- }
1158
- else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
1159
- object = object[value];
1160
- }
1161
- else if( object[value] !== undefined ) {
1162
- found = object[value];
1163
- return false;
1164
- }
1165
- else {
1166
- module.error(error.method, query);
1167
- return false;
1168
- }
1169
- });
1170
- }
1171
- if ( isFunction( found ) ) {
1172
- response = found.apply(context, passedArguments);
1173
- }
1174
- else if(found !== undefined) {
1175
- response = found;
1176
- }
1177
- if(Array.isArray(returnedValue)) {
1178
- returnedValue.push(response);
1179
- }
1180
- else if(returnedValue !== undefined) {
1181
- returnedValue = [returnedValue, response];
1182
- }
1183
- else if(response !== undefined) {
1184
- returnedValue = response;
1185
- }
1186
- return found;
1187
- }
1188
- };
1189
-
1190
- if(methodInvoked) {
1191
- if(instance === undefined) {
1192
- module.initialize();
1193
- }
1194
- instance.save.scroll();
1195
- instance.save.calculations();
1196
- module.invoke(query);
1197
- }
1198
- else {
1199
- if(instance !== undefined) {
1200
- instance.invoke('destroy');
1201
- }
1202
- module.initialize();
1203
- }
1204
- })
1205
- ;
1206
-
1207
- return (returnedValue !== undefined)
1208
- ? returnedValue
1209
- : this
1210
- ;
1211
- };
1212
-
1213
- $.fn.visibility.settings = {
1214
-
1215
- name : 'Visibility',
1216
- namespace : 'visibility',
1217
-
1218
- debug : false,
1219
- verbose : false,
1220
- performance : true,
1221
-
1222
- // whether to use mutation observers to follow changes
1223
- observeChanges : true,
1224
-
1225
- // check position immediately on init
1226
- initialCheck : true,
1227
-
1228
- // whether to refresh calculations after all page images load
1229
- refreshOnLoad : true,
1230
-
1231
- // whether to refresh calculations after page resize event
1232
- refreshOnResize : true,
1233
-
1234
- // should call callbacks on refresh event (resize, etc)
1235
- checkOnRefresh : true,
1236
-
1237
- // callback should only occur one time
1238
- once : true,
1239
-
1240
- // callback should fire continuously when evaluates to true
1241
- continuous : false,
1242
-
1243
- // offset to use with scroll top
1244
- offset : 0,
1245
-
1246
- // whether to include margin in elements position
1247
- includeMargin : false,
1248
-
1249
- // scroll context for visibility checks
1250
- context : window,
1251
-
1252
- // visibility check delay in ms (defaults to animationFrame)
1253
- throttle : false,
1254
-
1255
- // special visibility type (image, fixed)
1256
- type : false,
1257
-
1258
- // z-index to use with visibility 'fixed'
1259
- zIndex : '10',
1260
-
1261
- // image only animation settings
1262
- transition : 'fade in',
1263
- duration : 1000,
1264
-
1265
- // array of callbacks for percentage
1266
- onPassed : {},
1267
-
1268
- // standard callbacks
1269
- onOnScreen : false,
1270
- onOffScreen : false,
1271
- onPassing : false,
1272
- onTopVisible : false,
1273
- onBottomVisible : false,
1274
- onTopPassed : false,
1275
- onBottomPassed : false,
1276
-
1277
- // reverse callbacks
1278
- onPassingReverse : false,
1279
- onTopVisibleReverse : false,
1280
- onBottomVisibleReverse : false,
1281
- onTopPassedReverse : false,
1282
- onBottomPassedReverse : false,
1283
-
1284
- // special callbacks for image
1285
- onLoad : function() {},
1286
- onAllLoaded : function() {},
1287
-
1288
- // special callbacks for fixed position
1289
- onFixed : function() {},
1290
- onUnfixed : function() {},
1291
-
1292
- // utility callbacks
1293
- onUpdate : false, // disabled by default for performance
1294
- onRefresh : function(){},
1295
-
1296
- metadata : {
1297
- src: 'src'
1298
- },
1299
-
1300
- className: {
1301
- fixed : 'fixed',
1302
- placeholder : 'constraint',
1303
- visible : 'visible'
1304
- },
1305
-
1306
- error : {
1307
- method : 'The method you called is not defined.',
1308
- visible : 'Element is hidden, you must call refresh after element becomes visible'
1309
- }
1310
-
1311
- };
1312
1289
 
1313
- })( jQuery, window, document );
1290
+ };
1291
+ })(jQuery, window, document);