-
Notifications
You must be signed in to change notification settings - Fork 584
/
jquery.inview.js
107 lines (88 loc) · 3.53 KB
/
jquery.inview.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/**
* author Remy Sharp
* url http://remysharp.com/2009/01/26/element-in-view-event-plugin/
* fork https://github.com/zuk/jquery.inview
*/
(function($) {
'use strict';
function getScrollTop() {
return window.pageYOffset ||
document.documentElement.scrollTop ||
document.body.scrollTop;
}
function getViewportHeight() {
var height = window.innerHeight; // Safari, Opera
// if this is correct then return it. iPad has compat Mode, so will
// go into check clientHeight (which has the wrong value).
if (height) {
return height;
}
var mode = document.compatMode;
if ((mode || !$.support.boxModel)) { // IE, Gecko
height = (mode === 'CSS1Compat') ?
document.documentElement.clientHeight : // Standards
document.body.clientHeight; // Quirks
}
return height;
}
function offsetTop(debug) {
// Manually calculate offset rather than using jQuery's offset
// This works-around iOS < 4 on iPad giving incorrect value
// cf http://bugs.jquery.com/ticket/6446#comment:9
var curtop = 0;
for (var obj = debug; obj; obj = obj.offsetParent) {
curtop += obj.offsetTop;
}
return curtop;
}
function checkInView() {
var viewportTop = getScrollTop(),
viewportBottom = viewportTop + getViewportHeight();
$('.inview').each(function() {
var $el = $(this),
elTop = offsetTop(this),
elHeight = $el.height(),
elBottom = elTop + elHeight,
wasInView = $el.data('inview') || false,
offset = $el.data('offset') || 0,
inView = elTop >= viewportTop && elBottom <= viewportBottom,
isBottomVisible = elBottom + offset >= viewportTop && elTop <= viewportTop,
isTopVisible = elTop - offset <= viewportBottom && elBottom >= viewportBottom,
inViewWithOffset = inView || isBottomVisible || isTopVisible ||
(elTop <= viewportTop && elBottom >= viewportBottom);
if (inViewWithOffset) {
var visPart = (isTopVisible) ? 'top' : (isBottomVisible) ? 'bottom' : 'both';
if (!wasInView || wasInView !== visPart) {
$el.data('inview', visPart);
$el.trigger('inview', [true, visPart]);
}
} else if (!inView && wasInView) {
$el.data('inview', false);
$el.trigger('inview', [false]);
}
});
}
function createFunctionLimitedToOneExecutionPerDelay(fn, delay) {
var shouldRun = false;
var timer = null;
function runOncePerDelay() {
if (timer !== null) {
shouldRun = true;
return;
}
shouldRun = false;
fn();
timer = setTimeout(function() {
timer = null;
if (shouldRun) {
runOncePerDelay();
}
}, delay);
}
return runOncePerDelay;
}
// ready.inview kicks the event to pick up any elements already in view.
// note however, this only works if the plugin is included after the elements are bound to 'inview'
var runner = createFunctionLimitedToOneExecutionPerDelay(checkInView, 100);
$(window).on('checkInView.inview click.inview ready.inview scroll.inview resize.inview', runner);
})(jQuery);