]> git.mxchange.org Git - friendica.git/blob - view/theme/frio/frameworks/jquery-scrollspy/jquery-scrollspy.js
Merge pull request #2584 from rabuzarus/0906-profiles
[friendica.git] / view / theme / frio / frameworks / jquery-scrollspy / jquery-scrollspy.js
1 /*
2  * jQuery ScrollSpy Plugin
3  * Author: @sxalexander, softwarespot
4  * Licensed under the MIT license
5  */
6 (function jQueryScrollspy(window, $) {
7     // Plugin Logic
8
9     $.fn.extend({
10         scrollspy: function scrollspy(options, action) {
11             // If the options parameter is a string, then assume it's an 'action', therefore swap the parameters around
12             if (_isString(options)) {
13                 var tempOptions = action;
14
15                 // Set the action as the option parameter
16                 action = options;
17
18                 // Set to be the reference action pointed to
19                 options = tempOptions;
20             }
21
22             // override the default options with those passed to the plugin
23             options = $.extend({}, _defaults, options);
24
25             // sanitize the following option with the default value if the predicate fails
26             _sanitizeOption(options, _defaults, 'container', _isObject);
27
28             // cache the jQuery object
29             var $container = $(options.container);
30
31             // check if it's a valid jQuery selector
32             if ($container.length === 0) {
33                 return this;
34             }
35
36             // sanitize the following option with the default value if the predicate fails
37             _sanitizeOption(options, _defaults, 'namespace', _isString);
38
39             // check if the action is set to DESTROY/destroy
40             if (_isString(action) && action.toUpperCase() === 'DESTROY') {
41                 $container.off('scroll.' + options.namespace);
42                 return this;
43             }
44
45             // sanitize the following options with the default values if the predicates fails
46             _sanitizeOption(options, _defaults, 'buffer', $.isNumeric);
47             _sanitizeOption(options, _defaults, 'max', $.isNumeric);
48             _sanitizeOption(options, _defaults, 'min', $.isNumeric);
49
50             // callbacks
51             _sanitizeOption(options, _defaults, 'onEnter', $.isFunction);
52             _sanitizeOption(options, _defaults, 'onLeave', $.isFunction);
53             _sanitizeOption(options, _defaults, 'onLeaveTop', $.isFunction);
54             _sanitizeOption(options, _defaults, 'onLeaveBottom', $.isFunction);
55             _sanitizeOption(options, _defaults, 'onTick', $.isFunction);
56
57             if ($.isFunction(options.max)) {
58                 options.max = options.max();
59             }
60
61             if ($.isFunction(options.min)) {
62                 options.min = options.min();
63             }
64
65             // check if the mode is set to VERTICAL/vertical
66             var isVertical = window.String(options.mode).toUpperCase() === 'VERTICAL';
67
68             return this.each(function each() {
69                 // cache this
70                 var _this = this;
71
72                 // cache the jQuery object
73                 var $element = $(_this);
74
75                 // count the number of times a container is entered
76                 var enters = 0;
77
78                 // determine if the scroll is with inside the container
79                 var inside = false;
80
81                 // count the number of times a container is left
82                 var leaves = 0;
83
84                 // create a scroll listener for the container
85                 $container.on('scroll.' + options.namespace, function onScroll() {
86                     // cache the jQuery object
87                     var $this = $(this);
88
89                     // create a position object literal
90                     var position = {
91                         top: $this.scrollTop(),
92                         left: $this.scrollLeft(),
93                     };
94
95                     var containerHeight = $container.height();
96
97                     var max = options.max;
98
99                     var min = options.min;
100
101                     var xAndY = isVertical ? position.top + options.buffer : position.left + options.buffer;
102
103                     if (max === 0) {
104                         // get the maximum value based on either the height or the outer width
105                         max = isVertical ? containerHeight : $container.outerWidth() + $element.outerWidth();
106                     }
107
108                     // if we have reached the minimum bound, though are below the max
109                     if (xAndY >= min && xAndY <= max) {
110                         // trigger the 'scrollEnter' event
111                         if (!inside) {
112                             inside = true;
113                             enters++;
114
115                             // trigger the 'scrollEnter' event
116                             $element.trigger('scrollEnter', {
117                                 position: position,
118                             });
119
120                             // call the 'onEnter' function
121                             if (options.onEnter !== null) {
122                                 options.onEnter(_this, position);
123                             }
124                         }
125
126                         // trigger the 'scrollTick' event
127                         $element.trigger('scrollTick', {
128                             position: position,
129                             inside: inside,
130                             enters: enters,
131                             leaves: leaves,
132                         });
133
134                         // call the 'onTick' function
135                         if (options.onTick !== null) {
136                             options.onTick(_this, position, inside, enters, leaves);
137                         }
138                     } else {
139                         if (inside) {
140                             inside = false;
141                             leaves++;
142
143                             // trigger the 'scrollLeave' event
144                             $element.trigger('scrollLeave', {
145                                 position: position,
146                                 leaves: leaves,
147                             });
148
149                             // call the 'onLeave' function
150                             if (options.onLeave !== null) {
151                                 options.onLeave(_this, position);
152                             }
153
154                             if (xAndY <= min) {
155                                 // trigger the 'scrollLeaveTop' event
156                                 $element.trigger('scrollLeaveTop', {
157                                     position: position,
158                                     leaves: leaves,
159                                 });
160
161                                 // call the 'onLeaveTop' function
162                                 if (options.onLeaveTop !== null) {
163                                     options.onLeaveTop(_this, position);
164                                 }
165                             } else if (xAndY >= max) {
166                                 // trigger the 'scrollLeaveBottom' event
167                                 $element.trigger('scrollLeaveBottom', {
168                                     position: position,
169                                     leaves: leaves,
170                                 });
171
172                                 // call the 'onLeaveBottom' function
173                                 if (options.onLeaveBottom !== null) {
174                                     options.onLeaveBottom(_this, position);
175                                 }
176                             }
177                         } else {
178                             // Idea taken from: http://stackoverflow.com/questions/5353934/check-if-element-is-visible-on-screen
179                             var containerScrollTop = $container.scrollTop();
180
181                             // Get the element height
182                             var elementHeight = $element.height();
183
184                             // Get the element offset
185                             var elementOffsetTop = $element.offset().top;
186
187                             if ((elementOffsetTop < (containerHeight + containerScrollTop)) && (elementOffsetTop > (containerScrollTop - elementHeight))) {
188                                 // trigger the 'scrollView' event
189                                 $element.trigger('scrollView', {
190                                     position: position,
191                                 });
192
193                                 // call the 'onView' function
194                                 if (options.onView !== null) {
195                                     options.onView(_this, position);
196                                 }
197                             }
198                         }
199                     }
200                 });
201             });
202         },
203     });
204
205     // Fields (Private)
206
207     // Defaults
208
209     // default options
210     var _defaults = {
211         // the offset to be applied to the left and top positions of the container
212         buffer: 0,
213
214         // the element to apply the 'scrolling' event to (default window)
215         container: window,
216
217         // the maximum value of the X or Y coordinate, depending on mode the selected
218         max: 0,
219
220         // the maximum value of the X or Y coordinate, depending on mode the selected
221         min: 0,
222
223         // whether to listen to the X (horizontal) or Y (vertical) scrolling
224         mode: 'vertical',
225
226         // namespace to append to the 'scroll' event
227         namespace: 'scrollspy',
228
229         // call the following callback function every time the user enters the min / max zone
230         onEnter: null,
231
232         // call the following callback function every time the user leaves the min / max zone
233         onLeave: null,
234
235         // call the following callback function every time the user leaves the top zone
236         onLeaveTop: null,
237
238         // call the following callback function every time the user leaves the bottom zone
239         onLeaveBottom: null,
240
241         // call the following callback function on each scroll event within the min and max parameters
242         onTick: null,
243
244         // call the following callback function on each scroll event when the element is inside the viewable view port
245         onView: null,
246     };
247
248     // Methods (Private)
249
250     // check if a value is an object datatype
251     function _isObject(value) {
252         return $.type(value) === 'object';
253     }
254
255     // check if a value is a string datatype with a length greater than zero when whitespace is stripped
256     function _isString(value) {
257         return $.type(value) === 'string' && $.trim(value).length > 0;
258     }
259
260     // check if an option is correctly formatted using a predicate; otherwise, return the default value
261     function _sanitizeOption(options, defaults, property, predicate) {
262         // set the property to the default value if the predicate returned false
263         if (!predicate(options[property])) {
264             options[property] = defaults[property];
265         }
266     }
267 }(window, window.jQuery));