-
Notifications
You must be signed in to change notification settings - Fork 109
/
visibility.core.js
189 lines (168 loc) · 6.36 KB
/
visibility.core.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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
;(function (global) {
var lastId = -1;
// Visibility.js allow you to know, that your web page is in the background
// tab and thus not visible to the user. This library is wrap under
// Page Visibility API. It fix problems with different vendor prefixes and
// add high-level useful functions.
var self = {
// Call callback only when page become to visible for user or
// call it now if page is visible now or Page Visibility API
// doesn’t supported.
//
// Return false if API isn’t supported, true if page is already visible
// or listener ID (you can use it in `unbind` method) if page isn’t
// visible now.
//
// Visibility.onVisible(function () {
// startIntroAnimation();
// });
onVisible: function (callback) {
var support = self.isSupported();
if ( !support || !self.hidden() ) {
callback();
return support;
}
var listener = self.change(function (e, state) {
if ( !self.hidden() ) {
self.unbind(listener);
callback();
}
});
return listener;
},
// Call callback when visibility will be changed. First argument for
// callback will be original event object, second will be visibility
// state name.
//
// Return listener ID to unbind listener by `unbind` method.
//
// If Page Visibility API doesn’t supported method will be return false
// and callback never will be called.
//
// Visibility.change(function(e, state) {
// Statistics.visibilityChange(state);
// });
//
// It is just proxy to `visibilitychange` event, but use vendor prefix.
change: function (callback) {
if ( !self.isSupported() ) {
return false;
}
lastId += 1;
var number = lastId;
self._callbacks[number] = callback;
self._listen();
return number;
},
// Remove `change` listener by it ID.
//
// var id = Visibility.change(function(e, state) {
// firstChangeCallback();
// Visibility.unbind(id);
// });
unbind: function (id) {
delete self._callbacks[id];
},
// Call `callback` in any state, expect “prerender”. If current state
// is “prerender” it will wait until state will be changed.
// If Page Visibility API doesn’t supported, it will call `callback`
// immediately.
//
// Return false if API isn’t supported, true if page is already after
// prerendering or listener ID (you can use it in `unbind` method)
// if page is prerended now.
//
// Visibility.afterPrerendering(function () {
// Statistics.countVisitor();
// });
afterPrerendering: function (callback) {
var support = self.isSupported();
var prerender = 'prerender';
if ( !support || prerender != self.state() ) {
callback();
return support;
}
var listener = self.change(function (e, state) {
if ( prerender != state ) {
self.unbind(listener);
callback();
}
});
return listener;
},
// Return true if page now isn’t visible to user.
//
// if ( !Visibility.hidden() ) {
// VideoPlayer.play();
// }
//
// It is just proxy to `document.hidden`, but use vendor prefix.
hidden: function () {
return !!(self._doc.hidden || self._doc.webkitHidden);
},
// Return visibility state: 'visible', 'hidden' or 'prerender'.
//
// if ( 'prerender' == Visibility.state() ) {
// Statistics.pageIsPrerendering();
// }
//
// Don’t use `Visibility.state()` to detect, is page visible, because
// visibility states can extend in next API versions.
// Use more simpler and general `Visibility.hidden()` for this cases.
//
// It is just proxy to `document.visibilityState`, but use
// vendor prefix.
state: function () {
return self._doc.visibilityState ||
self._doc.webkitVisibilityState ||
'visible';
},
// Return true if browser support Page Visibility API.
// refs: https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
//
// if ( Visibility.isSupported() ) {
// Statistics.startTrackingVisibility();
// Visibility.change(function(e, state)) {
// Statistics.trackVisibility(state);
// });
// }
isSupported: function () {
return self._doc.hidden !== undefined || self._doc.webkitHidden !== undefined;
},
// Link to document object to change it in tests.
_doc: document || {},
// Callbacks from `change` method, that wait visibility changes.
_callbacks: { },
// Listener for `visibilitychange` event.
_change: function(event) {
var state = self.state();
for ( var i in self._callbacks ) {
self._callbacks[i].call(self._doc, event, state);
}
},
// Set listener for `visibilitychange` event.
_listen: function () {
if ( self._init ) {
return;
}
var event = 'visibilitychange';
if ( self._doc.webkitVisibilityState ) {
event = 'webkit' + event;
}
var listener = function () {
self._change.apply(self, arguments);
};
if ( self._doc.addEventListener ) {
self._doc.addEventListener(event, listener);
} else {
self._doc.attachEvent(event, listener);
}
self._init = true;
}
};
if ( typeof(module) != 'undefined' && module.exports ) {
module.exports = self;
} else {
global.Visibility = self;
}
})(this);