visibilityjs 1.1.0 → 1.2.0
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.
- checksums.yaml +4 -4
- data/ChangeLog.md +10 -2
- data/README.md +2 -2
- data/lib/{assets/javascripts/visibility.core.js → visibility.core.js} +37 -77
- data/lib/{assets/javascripts/visibility.fallback.js → visibility.fallback.js} +8 -8
- data/lib/visibility.js +4 -0
- data/lib/{assets/javascripts/visibility.timers.js → visibility.timers.js} +50 -55
- data/lib/visibilityjs.rb +9 -0
- metadata +9 -9
- data/lib/assets/javascripts/visibility.js +0 -390
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 67bc18a7e786dbc5e14e5c26e95f4afea84b89c9
|
4
|
+
data.tar.gz: 6a747d0bbac0a17f58bb2f468a671b99ff7fd5c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 475e0c05d111b930c38e6adb18c566a962819702d8f26e1e5a629a73e4b45cb044ac47c29815bb50fee151f9f58ff1969eb7503497bb3e5e4be33d767631f632
|
7
|
+
data.tar.gz: 0037c05474dde93f3bb1fa7fbb14d9d6d3e2a74b290ce25ad67512f9c1fb66cd8d50a51bc02132a1ed1b71e30bbf9b2719b7a3a0706cf3125c90f82154a3d000
|
data/ChangeLog.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
### 1.2.0 “Discoverer 5, spy”
|
2
|
+
* Allow to use in CommonJS.
|
3
|
+
* Release npm package.
|
4
|
+
* Reduce library size to 10 %.
|
5
|
+
* Allow to use latest version from master in Ruby Bundler.
|
6
|
+
* Method `hidden()` now always return boolean.
|
7
|
+
* Change repository URL to `github.com/ai/visibilityjs`.
|
8
|
+
|
1
9
|
## 1.1.0 “Explorer 6, photo”
|
2
10
|
* Prevent to run timer often, that it’s interval, when visibility was changed.
|
3
11
|
* Allow to install by Bower package manager.
|
@@ -8,7 +16,7 @@
|
|
8
16
|
* Remove jQuery.Chrono integration.
|
9
17
|
* Remove outdated Firefox prefix.
|
10
18
|
|
11
|
-
## 0.6.2 “Pioneer 4,
|
19
|
+
## 0.6.2 “Pioneer 4, American Sun”
|
12
20
|
* Decrease files size (by compressible code and UnglifyJS 2).
|
13
21
|
* Remove unnecessary vendor prefixes from fallback.
|
14
22
|
|
@@ -17,7 +25,7 @@
|
|
17
25
|
|
18
26
|
## 0.6 “Luna 1, Mechta”
|
19
27
|
* Methods onVisible and afterPrerendering return listener ID (by mcfedr).
|
20
|
-
* Fix documentation (by
|
28
|
+
* Fix documentation (by Erwänn Mest).
|
21
29
|
|
22
30
|
## 0.5 “SCORE, communication”
|
23
31
|
* Split library to core and timers modules.
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Visibility.js
|
2
2
|
|
3
|
-
<img align="right" width="100" src="http://ai.github.io/
|
3
|
+
<img align="right" width="100" src="http://ai.github.io/visibilityjs/logo.svg" title="Visibility.js logo by Eugenia Tuchapets">
|
4
4
|
|
5
5
|
Visibility.js is a wrapper for the [Page Visibility API]. It hides vendor prefixes and adds high level functions.
|
6
6
|
|
@@ -292,7 +292,7 @@ Add to your site:
|
|
292
292
|
### Other
|
293
293
|
|
294
294
|
If you need just a files, you can take already minified packages from
|
295
|
-
[github.com/ai/
|
295
|
+
[github.com/ai/visibilityjs/releases](https://github.com/ai/visibilityjs/releases).
|
296
296
|
|
297
297
|
## Contributing
|
298
298
|
|
@@ -1,15 +1,13 @@
|
|
1
|
-
;(function (
|
1
|
+
;(function (global) {
|
2
2
|
"use strict";
|
3
3
|
|
4
|
-
var
|
5
|
-
return (variable != undefined);
|
6
|
-
};
|
4
|
+
var lastId = -1;
|
7
5
|
|
8
6
|
// Visibility.js allow you to know, that your web page is in the background
|
9
7
|
// tab and thus not visible to the user. This library is wrap under
|
10
8
|
// Page Visibility API. It fix problems with different vendor prefixes and
|
11
9
|
// add high-level useful functions.
|
12
|
-
var self =
|
10
|
+
var self = {
|
13
11
|
|
14
12
|
// Call callback only when page become to visible for user or
|
15
13
|
// call it now if page is visible now or Page Visibility API
|
@@ -23,9 +21,10 @@
|
|
23
21
|
// startIntroAnimation();
|
24
22
|
// });
|
25
23
|
onVisible: function (callback) {
|
26
|
-
|
24
|
+
var support = self.isSupported();
|
25
|
+
if ( !support || !self.hidden() ) {
|
27
26
|
callback();
|
28
|
-
return
|
27
|
+
return support;
|
29
28
|
}
|
30
29
|
|
31
30
|
var listener = self.change(function (e, state) {
|
@@ -55,8 +54,8 @@
|
|
55
54
|
if ( !self.isSupported() ) {
|
56
55
|
return false;
|
57
56
|
}
|
58
|
-
|
59
|
-
var number =
|
57
|
+
lastId += 1;
|
58
|
+
var number = lastId;
|
60
59
|
self._callbacks[number] = callback;
|
61
60
|
self._listen();
|
62
61
|
return number;
|
@@ -85,13 +84,16 @@
|
|
85
84
|
// Statistics.countVisitor();
|
86
85
|
// });
|
87
86
|
afterPrerendering: function (callback) {
|
88
|
-
|
87
|
+
var support = self.isSupported();
|
88
|
+
var prerender = 'prerender';
|
89
|
+
|
90
|
+
if ( !support || prerender != self.state() ) {
|
89
91
|
callback();
|
90
|
-
return
|
92
|
+
return support;
|
91
93
|
}
|
92
94
|
|
93
95
|
var listener = self.change(function (e, state) {
|
94
|
-
if (
|
96
|
+
if ( prerender != state ) {
|
95
97
|
self.unbind(listener);
|
96
98
|
callback();
|
97
99
|
}
|
@@ -107,7 +109,7 @@
|
|
107
109
|
//
|
108
110
|
// It is just proxy to `document.hidden`, but use vendor prefix.
|
109
111
|
hidden: function () {
|
110
|
-
return self.
|
112
|
+
return !!(self._doc.hidden || self._doc.webkitHidden);
|
111
113
|
},
|
112
114
|
|
113
115
|
// Return visibility state: 'visible', 'hidden' or 'prerender'.
|
@@ -123,7 +125,9 @@
|
|
123
125
|
// It is just proxy to `document.visibilityState`, but use
|
124
126
|
// vendor prefix.
|
125
127
|
state: function () {
|
126
|
-
return self.
|
128
|
+
return self._doc.visibilityState ||
|
129
|
+
self._doc.webkitVisibilityState ||
|
130
|
+
'visible';
|
127
131
|
},
|
128
132
|
|
129
133
|
// Return true if browser support Page Visibility API.
|
@@ -135,66 +139,16 @@
|
|
135
139
|
// });
|
136
140
|
// }
|
137
141
|
isSupported: function () {
|
138
|
-
return
|
142
|
+
return !!(self._doc.visibilityState ||
|
143
|
+
self._doc.webkitVisibilityState);
|
139
144
|
},
|
140
145
|
|
141
146
|
// Link to document object to change it in tests.
|
142
|
-
_doc:
|
143
|
-
|
144
|
-
// Vendor prefix cached by `_prefix` function.
|
145
|
-
_cached: null,
|
146
|
-
|
147
|
-
// Is listener for `visibilitychange` event is already added
|
148
|
-
// by `_listen` method.
|
149
|
-
_enable: false,
|
150
|
-
|
151
|
-
// Last timer number.
|
152
|
-
_lastId: -1,
|
147
|
+
_doc: document || {},
|
153
148
|
|
154
149
|
// Callbacks from `change` method, that wait visibility changes.
|
155
150
|
_callbacks: { },
|
156
151
|
|
157
|
-
// Variable to check hidden-visible state changes.
|
158
|
-
_wasHidden: false,
|
159
|
-
|
160
|
-
// Initialize variables on page loading.
|
161
|
-
_init: function () {
|
162
|
-
self._wasHidden = self.hidden();
|
163
|
-
},
|
164
|
-
|
165
|
-
// Detect vendor prefix and return it.
|
166
|
-
_prefix: function () {
|
167
|
-
if ( null !== self._cached ) {
|
168
|
-
return self._cached;
|
169
|
-
}
|
170
|
-
if ( defined(self._doc.visibilityState) ) {
|
171
|
-
return self._cached = '';
|
172
|
-
}
|
173
|
-
if ( defined(self._doc.webkitVisibilityState) ) {
|
174
|
-
return self._cached = 'webkit';
|
175
|
-
}
|
176
|
-
},
|
177
|
-
|
178
|
-
// Return property name with vendor prefix.
|
179
|
-
_name: function (name) {
|
180
|
-
var prefix = self._prefix();
|
181
|
-
if ( '' == prefix ) {
|
182
|
-
return name;
|
183
|
-
} else {
|
184
|
-
return prefix +
|
185
|
-
name.substr(0, 1).toUpperCase() + name.substr(1);
|
186
|
-
}
|
187
|
-
},
|
188
|
-
|
189
|
-
// Return document’s property value with name with vendor prefix.
|
190
|
-
// If API is not support, it will retun `unsupported` value.
|
191
|
-
_prop: function (name, unsupported) {
|
192
|
-
if ( !self.isSupported() ) {
|
193
|
-
return unsupported;
|
194
|
-
}
|
195
|
-
return self._doc[self._name(name)];
|
196
|
-
},
|
197
|
-
|
198
152
|
// Listener for `visibilitychange` event.
|
199
153
|
_change: function(event) {
|
200
154
|
var state = self.state();
|
@@ -202,30 +156,36 @@
|
|
202
156
|
for ( var i in self._callbacks ) {
|
203
157
|
self._callbacks[i].call(self._doc, event, state);
|
204
158
|
}
|
205
|
-
|
206
|
-
self._wasHidden = self.hidden();
|
207
159
|
},
|
208
160
|
|
209
161
|
// Set listener for `visibilitychange` event.
|
210
162
|
_listen: function () {
|
211
|
-
if ( self.
|
163
|
+
if ( self._init ) {
|
212
164
|
return;
|
213
165
|
}
|
214
|
-
|
166
|
+
|
167
|
+
var event = 'visibilitychange';
|
168
|
+
if ( self._doc.webkitVisibilityState ) {
|
169
|
+
event = 'webkit' + event;
|
170
|
+
}
|
171
|
+
|
215
172
|
var listener = function () {
|
216
|
-
self._change.apply(
|
173
|
+
self._change.apply(self, arguments);
|
217
174
|
};
|
218
175
|
if ( self._doc.addEventListener ) {
|
219
|
-
self._doc.addEventListener(event, listener
|
176
|
+
self._doc.addEventListener(event, listener);
|
220
177
|
} else {
|
221
178
|
self._doc.attachEvent(event, listener);
|
222
179
|
}
|
223
|
-
self.
|
224
|
-
self._wasHidden = self.hidden();
|
180
|
+
self._init = true;
|
225
181
|
}
|
226
182
|
|
227
183
|
};
|
228
184
|
|
229
|
-
|
185
|
+
if ( typeof(module) != 'undefined' && module.exports ) {
|
186
|
+
module.exports = self;
|
187
|
+
} else {
|
188
|
+
global.Visibility = self;
|
189
|
+
}
|
230
190
|
|
231
|
-
})();
|
191
|
+
})(this);
|
@@ -8,7 +8,7 @@
|
|
8
8
|
//
|
9
9
|
// For Firefox 5–9 it will be better to use MozVisibility hack without
|
10
10
|
// this issue. See <https://github.com/private-face/mozvisibility>.
|
11
|
-
;(function () {
|
11
|
+
;(function (document) {
|
12
12
|
"use strict";
|
13
13
|
|
14
14
|
if ( document.visibilityState || document.webkitVisibilityState ) {
|
@@ -34,22 +34,22 @@
|
|
34
34
|
}
|
35
35
|
}
|
36
36
|
|
37
|
-
var
|
37
|
+
var onFocus = function () {
|
38
38
|
document.hidden = false;
|
39
39
|
document.visibilityState = 'visible';
|
40
40
|
fireEvent();
|
41
41
|
};
|
42
|
-
var
|
42
|
+
var onBlur = function () {
|
43
43
|
document.hidden = true;
|
44
44
|
document.visibilityState = 'hidden';
|
45
45
|
fireEvent();
|
46
46
|
}
|
47
47
|
|
48
48
|
if ( document.addEventListener ) {
|
49
|
-
window.addEventListener('focus',
|
50
|
-
window.addEventListener('blur',
|
49
|
+
window.addEventListener('focus', onFocus, true);
|
50
|
+
window.addEventListener('blur', onBlur, true);
|
51
51
|
} else {
|
52
|
-
document.attachEvent('onfocusin',
|
53
|
-
document.attachEvent('onfocusout',
|
52
|
+
document.attachEvent('onfocusin', onFocus);
|
53
|
+
document.attachEvent('onfocusout', onBlur);
|
54
54
|
}
|
55
|
-
})();
|
55
|
+
})(document);
|
data/lib/visibility.js
ADDED
@@ -1,13 +1,9 @@
|
|
1
|
-
;(function () {
|
1
|
+
;(function (window) {
|
2
2
|
"use strict";
|
3
3
|
|
4
|
-
var
|
5
|
-
return ('undefined' != typeof(variable));
|
6
|
-
};
|
4
|
+
var lastTimer = -1;
|
7
5
|
|
8
|
-
var
|
9
|
-
|
10
|
-
var timers = {
|
6
|
+
var install = function (Visibility) {
|
11
7
|
|
12
8
|
// Run callback every `interval` milliseconds if page is visible and
|
13
9
|
// every `hiddenInterval` milliseconds if page is hidden.
|
@@ -32,29 +28,29 @@
|
|
32
28
|
// so don’t use it in `clearInterval`.
|
33
29
|
//
|
34
30
|
// On change state from hidden to visible timers will be execute.
|
35
|
-
every
|
36
|
-
|
31
|
+
Visibility.every = function (interval, hiddenInterval, callback) {
|
32
|
+
Visibility._time();
|
37
33
|
|
38
|
-
if ( !
|
34
|
+
if ( !callback ) {
|
39
35
|
callback = hiddenInterval;
|
40
36
|
hiddenInterval = null;
|
41
37
|
}
|
42
38
|
|
43
|
-
|
44
|
-
var number =
|
39
|
+
lastTimer += 1;
|
40
|
+
var number = lastTimer;
|
45
41
|
|
46
|
-
|
42
|
+
Visibility._timers[number] = {
|
47
43
|
visible: interval,
|
48
44
|
hidden: hiddenInterval,
|
49
45
|
callback: callback
|
50
46
|
};
|
51
|
-
|
47
|
+
Visibility._run(number, false);
|
52
48
|
|
53
|
-
if (
|
54
|
-
|
49
|
+
if ( Visibility.isSupported() ) {
|
50
|
+
Visibility._listen();
|
55
51
|
}
|
56
52
|
return number;
|
57
|
-
}
|
53
|
+
};
|
58
54
|
|
59
55
|
// Stop timer from `every` method by it ID (`every` method return it).
|
60
56
|
//
|
@@ -64,36 +60,31 @@
|
|
64
60
|
// $('.stopSlideshow').click(function () {
|
65
61
|
// Visibility.stop(slideshow);
|
66
62
|
// });
|
67
|
-
stop
|
68
|
-
|
69
|
-
if ( !defined(timer) ) {
|
63
|
+
Visibility.stop = function(id) {
|
64
|
+
if ( !Visibility._timers[id] ) {
|
70
65
|
return false;
|
71
66
|
}
|
72
|
-
|
73
|
-
delete
|
74
|
-
return
|
75
|
-
}
|
76
|
-
|
77
|
-
// Last timer number.
|
78
|
-
_lastTimer: -1,
|
67
|
+
Visibility._stop(id);
|
68
|
+
delete Visibility._timers[id];
|
69
|
+
return true;
|
70
|
+
};
|
79
71
|
|
80
72
|
// Callbacks and intervals added by `every` method.
|
81
|
-
_timers
|
82
|
-
|
83
|
-
// Is setInterval method detected and listener is binded.
|
84
|
-
_timed: false,
|
73
|
+
Visibility._timers = { };
|
85
74
|
|
86
75
|
// Initialize variables on page loading.
|
87
|
-
_time
|
88
|
-
if (
|
76
|
+
Visibility._time = function () {
|
77
|
+
if ( Visibility._timed ) {
|
89
78
|
return;
|
90
79
|
}
|
91
|
-
|
80
|
+
Visibility._timed = true;
|
81
|
+
Visibility._wasHidden = Visibility.hidden();
|
92
82
|
|
93
|
-
|
94
|
-
|
83
|
+
Visibility.change(function () {
|
84
|
+
Visibility._stopRun();
|
85
|
+
Visibility._wasHidden = Visibility.hidden();
|
95
86
|
});
|
96
|
-
}
|
87
|
+
};
|
97
88
|
|
98
89
|
// Try to run timer from every method by it’s ID. It will be use
|
99
90
|
// `interval` or `hiddenInterval` depending on visibility state.
|
@@ -101,10 +92,11 @@
|
|
101
92
|
// it will not run timer.
|
102
93
|
//
|
103
94
|
// Argument `runNow` say, that timers must be execute now too.
|
104
|
-
_run
|
95
|
+
Visibility._run = function (id, runNow) {
|
105
96
|
var interval,
|
106
|
-
timer =
|
107
|
-
|
97
|
+
timer = Visibility._timers[id];
|
98
|
+
|
99
|
+
if ( Visibility.hidden() ) {
|
108
100
|
if ( null === timer.hidden ) {
|
109
101
|
return;
|
110
102
|
}
|
@@ -135,34 +127,37 @@
|
|
135
127
|
} else {
|
136
128
|
timer.id = setInterval(runner, interval);
|
137
129
|
}
|
138
|
-
}
|
130
|
+
};
|
139
131
|
|
140
132
|
// Stop timer from `every` method by it’s ID.
|
141
|
-
_stop
|
142
|
-
var timer =
|
133
|
+
Visibility._stop = function (id) {
|
134
|
+
var timer = Visibility._timers[id];
|
143
135
|
clearInterval(timer.id);
|
144
136
|
clearTimeout(timer.delay);
|
145
137
|
delete timer.id;
|
146
138
|
delete timer.delay;
|
147
|
-
}
|
139
|
+
};
|
148
140
|
|
149
141
|
// Listener for `visibilitychange` event.
|
150
|
-
_stopRun
|
151
|
-
var isHidden =
|
152
|
-
wasHidden =
|
142
|
+
Visibility._stopRun = function (event) {
|
143
|
+
var isHidden = Visibility.hidden(),
|
144
|
+
wasHidden = Visibility._wasHidden;
|
153
145
|
|
154
146
|
if ( (isHidden && !wasHidden) || (!isHidden && wasHidden) ) {
|
155
|
-
for ( var i in
|
156
|
-
|
157
|
-
|
147
|
+
for ( var i in Visibility._timers ) {
|
148
|
+
Visibility._stop(i);
|
149
|
+
Visibility._run(i, !isHidden);
|
158
150
|
}
|
159
151
|
}
|
160
|
-
}
|
152
|
+
};
|
161
153
|
|
162
|
-
|
154
|
+
return Visibility;
|
155
|
+
}
|
163
156
|
|
164
|
-
|
165
|
-
|
157
|
+
if ( typeof(module) != 'undefined' && module.exports ) {
|
158
|
+
module.exports = install(require('./visibility.core'));
|
159
|
+
} else {
|
160
|
+
install(window.Visibility)
|
166
161
|
}
|
167
162
|
|
168
|
-
})();
|
163
|
+
})(window);
|
data/lib/visibilityjs.rb
CHANGED
@@ -1,8 +1,17 @@
|
|
1
1
|
# Used only for Ruby on Rails gem to tell, that gem contain `lib/assets` with
|
2
2
|
# visibility.js file.
|
3
3
|
module VisibilityJs
|
4
|
+
|
5
|
+
# Add assets paths to standalone Sprockets environment.
|
6
|
+
def self.install(sprockets)
|
7
|
+
sprockets.append_path(Pathname(__FILE__).dirname)
|
8
|
+
end
|
9
|
+
|
4
10
|
module Rails
|
5
11
|
class Engine < ::Rails::Engine
|
12
|
+
initializer 'visibilityjs' do
|
13
|
+
VisibilityJs.install(::Rails.application.assets)
|
14
|
+
end
|
6
15
|
end
|
7
16
|
end
|
8
17
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: visibilityjs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrey Sitnik
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-01
|
11
|
+
date: 2014-03-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sprockets
|
@@ -39,12 +39,12 @@ files:
|
|
39
39
|
- ChangeLog.md
|
40
40
|
- LICENSE
|
41
41
|
- README.md
|
42
|
-
- lib/
|
43
|
-
- lib/
|
44
|
-
- lib/
|
45
|
-
- lib/
|
42
|
+
- lib/visibility.core.js
|
43
|
+
- lib/visibility.fallback.js
|
44
|
+
- lib/visibility.js
|
45
|
+
- lib/visibility.timers.js
|
46
46
|
- lib/visibilityjs.rb
|
47
|
-
homepage: https://github.com/ai/
|
47
|
+
homepage: https://github.com/ai/visibilityjs
|
48
48
|
licenses:
|
49
49
|
- MIT
|
50
50
|
metadata: {}
|
@@ -64,8 +64,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
64
64
|
version: '0'
|
65
65
|
requirements: []
|
66
66
|
rubyforge_project:
|
67
|
-
rubygems_version: 2.2.
|
67
|
+
rubygems_version: 2.2.2
|
68
68
|
signing_key:
|
69
69
|
specification_version: 4
|
70
|
-
summary:
|
70
|
+
summary: Wrapper for the Page Visibility API
|
71
71
|
test_files: []
|
@@ -1,390 +0,0 @@
|
|
1
|
-
;(function (undefined) {
|
2
|
-
"use strict";
|
3
|
-
|
4
|
-
var defined = function (variable) {
|
5
|
-
return (variable != undefined);
|
6
|
-
};
|
7
|
-
|
8
|
-
// Visibility.js allow you to know, that your web page is in the background
|
9
|
-
// tab and thus not visible to the user. This library is wrap under
|
10
|
-
// Page Visibility API. It fix problems with different vendor prefixes and
|
11
|
-
// add high-level useful functions.
|
12
|
-
var self = window.Visibility = {
|
13
|
-
|
14
|
-
// Call callback only when page become to visible for user or
|
15
|
-
// call it now if page is visible now or Page Visibility API
|
16
|
-
// doesn’t supported.
|
17
|
-
//
|
18
|
-
// Return false if API isn’t supported, true if page is already visible
|
19
|
-
// or listener ID (you can use it in `unbind` method) if page isn’t
|
20
|
-
// visible now.
|
21
|
-
//
|
22
|
-
// Visibility.onVisible(function () {
|
23
|
-
// startIntroAnimation();
|
24
|
-
// });
|
25
|
-
onVisible: function (callback) {
|
26
|
-
if ( !self.isSupported() || !self.hidden() ) {
|
27
|
-
callback();
|
28
|
-
return self.isSupported();
|
29
|
-
}
|
30
|
-
|
31
|
-
var listener = self.change(function (e, state) {
|
32
|
-
if ( !self.hidden() ) {
|
33
|
-
self.unbind(listener);
|
34
|
-
callback();
|
35
|
-
}
|
36
|
-
});
|
37
|
-
return listener;
|
38
|
-
},
|
39
|
-
|
40
|
-
// Call callback when visibility will be changed. First argument for
|
41
|
-
// callback will be original event object, second will be visibility
|
42
|
-
// state name.
|
43
|
-
//
|
44
|
-
// Return listener ID to unbind listener by `unbind` method.
|
45
|
-
//
|
46
|
-
// If Page Visibility API doesn’t supported method will be return false
|
47
|
-
// and callback never will be called.
|
48
|
-
//
|
49
|
-
// Visibility.change(function(e, state) {
|
50
|
-
// Statistics.visibilityChange(state);
|
51
|
-
// });
|
52
|
-
//
|
53
|
-
// It is just proxy to `visibilitychange` event, but use vendor prefix.
|
54
|
-
change: function (callback) {
|
55
|
-
if ( !self.isSupported() ) {
|
56
|
-
return false;
|
57
|
-
}
|
58
|
-
self._lastId += 1;
|
59
|
-
var number = self._lastId;
|
60
|
-
self._callbacks[number] = callback;
|
61
|
-
self._listen();
|
62
|
-
return number;
|
63
|
-
},
|
64
|
-
|
65
|
-
// Remove `change` listener by it ID.
|
66
|
-
//
|
67
|
-
// var id = Visibility.change(function(e, state) {
|
68
|
-
// firstChangeCallback();
|
69
|
-
// Visibility.unbind(id);
|
70
|
-
// });
|
71
|
-
unbind: function (id) {
|
72
|
-
delete self._callbacks[id];
|
73
|
-
},
|
74
|
-
|
75
|
-
// Call `callback` in any state, expect “prerender”. If current state
|
76
|
-
// is “prerender” it will wait until state will be changed.
|
77
|
-
// If Page Visibility API doesn’t supported, it will call `callback`
|
78
|
-
// immediately.
|
79
|
-
//
|
80
|
-
// Return false if API isn’t supported, true if page is already after
|
81
|
-
// prerendering or listener ID (you can use it in `unbind` method)
|
82
|
-
// if page is prerended now.
|
83
|
-
//
|
84
|
-
// Visibility.afterPrerendering(function () {
|
85
|
-
// Statistics.countVisitor();
|
86
|
-
// });
|
87
|
-
afterPrerendering: function (callback) {
|
88
|
-
if ( !self.isSupported() || 'prerender' != self.state() ) {
|
89
|
-
callback();
|
90
|
-
return self.isSupported();
|
91
|
-
}
|
92
|
-
|
93
|
-
var listener = self.change(function (e, state) {
|
94
|
-
if ( 'prerender' != state ) {
|
95
|
-
self.unbind(listener);
|
96
|
-
callback();
|
97
|
-
}
|
98
|
-
});
|
99
|
-
return listener;
|
100
|
-
},
|
101
|
-
|
102
|
-
// Return true if page now isn’t visible to user.
|
103
|
-
//
|
104
|
-
// if ( !Visibility.hidden() ) {
|
105
|
-
// VideoPlayer.play();
|
106
|
-
// }
|
107
|
-
//
|
108
|
-
// It is just proxy to `document.hidden`, but use vendor prefix.
|
109
|
-
hidden: function () {
|
110
|
-
return self._prop('hidden', false);
|
111
|
-
},
|
112
|
-
|
113
|
-
// Return visibility state: 'visible', 'hidden' or 'prerender'.
|
114
|
-
//
|
115
|
-
// if ( 'prerender' == Visibility.state() ) {
|
116
|
-
// Statistics.pageIsPrerendering();
|
117
|
-
// }
|
118
|
-
//
|
119
|
-
// Don’t use `Visibility.state()` to detect, is page visible, because
|
120
|
-
// visibility states can extend in next API versions.
|
121
|
-
// Use more simpler and general `Visibility.hidden()` for this cases.
|
122
|
-
//
|
123
|
-
// It is just proxy to `document.visibilityState`, but use
|
124
|
-
// vendor prefix.
|
125
|
-
state: function () {
|
126
|
-
return self._prop('visibilityState', 'visible');
|
127
|
-
},
|
128
|
-
|
129
|
-
// Return true if browser support Page Visibility API.
|
130
|
-
//
|
131
|
-
// if ( Visibility.isSupported() ) {
|
132
|
-
// Statistics.startTrackingVisibility();
|
133
|
-
// Visibility.change(function(e, state)) {
|
134
|
-
// Statistics.trackVisibility(state);
|
135
|
-
// });
|
136
|
-
// }
|
137
|
-
isSupported: function () {
|
138
|
-
return defined(self._prefix());
|
139
|
-
},
|
140
|
-
|
141
|
-
// Link to document object to change it in tests.
|
142
|
-
_doc: window.document,
|
143
|
-
|
144
|
-
// Vendor prefix cached by `_prefix` function.
|
145
|
-
_cached: null,
|
146
|
-
|
147
|
-
// Is listener for `visibilitychange` event is already added
|
148
|
-
// by `_listen` method.
|
149
|
-
_enable: false,
|
150
|
-
|
151
|
-
// Last timer number.
|
152
|
-
_lastId: -1,
|
153
|
-
|
154
|
-
// Callbacks from `change` method, that wait visibility changes.
|
155
|
-
_callbacks: { },
|
156
|
-
|
157
|
-
// Variable to check hidden-visible state changes.
|
158
|
-
_wasHidden: false,
|
159
|
-
|
160
|
-
// Initialize variables on page loading.
|
161
|
-
_init: function () {
|
162
|
-
self._wasHidden = self.hidden();
|
163
|
-
},
|
164
|
-
|
165
|
-
// Detect vendor prefix and return it.
|
166
|
-
_prefix: function () {
|
167
|
-
if ( null !== self._cached ) {
|
168
|
-
return self._cached;
|
169
|
-
}
|
170
|
-
if ( defined(self._doc.visibilityState) ) {
|
171
|
-
return self._cached = '';
|
172
|
-
}
|
173
|
-
if ( defined(self._doc.webkitVisibilityState) ) {
|
174
|
-
return self._cached = 'webkit';
|
175
|
-
}
|
176
|
-
},
|
177
|
-
|
178
|
-
// Return property name with vendor prefix.
|
179
|
-
_name: function (name) {
|
180
|
-
var prefix = self._prefix();
|
181
|
-
if ( '' == prefix ) {
|
182
|
-
return name;
|
183
|
-
} else {
|
184
|
-
return prefix +
|
185
|
-
name.substr(0, 1).toUpperCase() + name.substr(1);
|
186
|
-
}
|
187
|
-
},
|
188
|
-
|
189
|
-
// Return document’s property value with name with vendor prefix.
|
190
|
-
// If API is not support, it will retun `unsupported` value.
|
191
|
-
_prop: function (name, unsupported) {
|
192
|
-
if ( !self.isSupported() ) {
|
193
|
-
return unsupported;
|
194
|
-
}
|
195
|
-
return self._doc[self._name(name)];
|
196
|
-
},
|
197
|
-
|
198
|
-
// Listener for `visibilitychange` event.
|
199
|
-
_change: function(event) {
|
200
|
-
var state = self.state();
|
201
|
-
|
202
|
-
for ( var i in self._callbacks ) {
|
203
|
-
self._callbacks[i].call(self._doc, event, state);
|
204
|
-
}
|
205
|
-
|
206
|
-
self._wasHidden = self.hidden();
|
207
|
-
},
|
208
|
-
|
209
|
-
// Set listener for `visibilitychange` event.
|
210
|
-
_listen: function () {
|
211
|
-
if ( self._enable ) {
|
212
|
-
return;
|
213
|
-
}
|
214
|
-
var event = self._prefix() + 'visibilitychange';
|
215
|
-
var listener = function () {
|
216
|
-
self._change.apply(Visibility, arguments);
|
217
|
-
};
|
218
|
-
if ( self._doc.addEventListener ) {
|
219
|
-
self._doc.addEventListener(event, listener, false);
|
220
|
-
} else {
|
221
|
-
self._doc.attachEvent(event, listener);
|
222
|
-
}
|
223
|
-
self._enable = true;
|
224
|
-
self._wasHidden = self.hidden();
|
225
|
-
}
|
226
|
-
|
227
|
-
};
|
228
|
-
|
229
|
-
self._init();
|
230
|
-
|
231
|
-
|
232
|
-
var timers = {
|
233
|
-
|
234
|
-
// Run callback every `interval` milliseconds if page is visible and
|
235
|
-
// every `hiddenInterval` milliseconds if page is hidden.
|
236
|
-
//
|
237
|
-
// Visibility.every(60 * 1000, 5 * 60 * 1000, function () {
|
238
|
-
// checkNewMails();
|
239
|
-
// });
|
240
|
-
//
|
241
|
-
// You can skip `hiddenInterval` and callback will be called only if
|
242
|
-
// page is visible.
|
243
|
-
//
|
244
|
-
// Visibility.every(1000, function () {
|
245
|
-
// updateCountdown();
|
246
|
-
// });
|
247
|
-
//
|
248
|
-
// It is analog of `setInterval(callback, interval)` but use visibility
|
249
|
-
// state.
|
250
|
-
//
|
251
|
-
// It return timer ID, that you can use in `Visibility.stop(id)` to stop
|
252
|
-
// timer (`clearInterval` analog).
|
253
|
-
// Warning: timer ID is different from interval ID from `setInterval`,
|
254
|
-
// so don’t use it in `clearInterval`.
|
255
|
-
//
|
256
|
-
// On change state from hidden to visible timers will be execute.
|
257
|
-
every: function (interval, hiddenInterval, callback) {
|
258
|
-
self._time();
|
259
|
-
|
260
|
-
if ( !defined(callback) ) {
|
261
|
-
callback = hiddenInterval;
|
262
|
-
hiddenInterval = null;
|
263
|
-
}
|
264
|
-
|
265
|
-
self._lastTimer += 1;
|
266
|
-
var number = self._lastTimer;
|
267
|
-
|
268
|
-
self._timers[number] = {
|
269
|
-
visible: interval,
|
270
|
-
hidden: hiddenInterval,
|
271
|
-
callback: callback
|
272
|
-
};
|
273
|
-
self._run(number, false);
|
274
|
-
|
275
|
-
if ( self.isSupported() ) {
|
276
|
-
self._listen();
|
277
|
-
}
|
278
|
-
return number;
|
279
|
-
},
|
280
|
-
|
281
|
-
// Stop timer from `every` method by it ID (`every` method return it).
|
282
|
-
//
|
283
|
-
// slideshow = Visibility.every(5 * 1000, function () {
|
284
|
-
// changeSlide();
|
285
|
-
// });
|
286
|
-
// $('.stopSlideshow').click(function () {
|
287
|
-
// Visibility.stop(slideshow);
|
288
|
-
// });
|
289
|
-
stop: function(id) {
|
290
|
-
var timer = self._timers[id]
|
291
|
-
if ( !defined(timer) ) {
|
292
|
-
return false;
|
293
|
-
}
|
294
|
-
self._stop(id);
|
295
|
-
delete self._timers[id];
|
296
|
-
return timer;
|
297
|
-
},
|
298
|
-
|
299
|
-
// Last timer number.
|
300
|
-
_lastTimer: -1,
|
301
|
-
|
302
|
-
// Callbacks and intervals added by `every` method.
|
303
|
-
_timers: { },
|
304
|
-
|
305
|
-
// Is setInterval method detected and listener is binded.
|
306
|
-
_timed: false,
|
307
|
-
|
308
|
-
// Initialize variables on page loading.
|
309
|
-
_time: function () {
|
310
|
-
if ( self._timed ) {
|
311
|
-
return;
|
312
|
-
}
|
313
|
-
self._timed = true;
|
314
|
-
|
315
|
-
self.change(function () {
|
316
|
-
self._stopRun()
|
317
|
-
});
|
318
|
-
},
|
319
|
-
|
320
|
-
// Try to run timer from every method by it’s ID. It will be use
|
321
|
-
// `interval` or `hiddenInterval` depending on visibility state.
|
322
|
-
// If page is hidden and `hiddenInterval` is null,
|
323
|
-
// it will not run timer.
|
324
|
-
//
|
325
|
-
// Argument `runNow` say, that timers must be execute now too.
|
326
|
-
_run: function (id, runNow) {
|
327
|
-
var interval,
|
328
|
-
timer = self._timers[id];
|
329
|
-
if ( self.hidden() ) {
|
330
|
-
if ( null === timer.hidden ) {
|
331
|
-
return;
|
332
|
-
}
|
333
|
-
interval = timer.hidden;
|
334
|
-
} else {
|
335
|
-
interval = timer.visible;
|
336
|
-
}
|
337
|
-
|
338
|
-
var runner = function () {
|
339
|
-
timer.last = new Date();
|
340
|
-
timer.callback.call(window);
|
341
|
-
}
|
342
|
-
|
343
|
-
if ( runNow ) {
|
344
|
-
var now = new Date();
|
345
|
-
var last = now - timer.last ;
|
346
|
-
|
347
|
-
if ( interval > last ) {
|
348
|
-
timer.delay = setTimeout(function () {
|
349
|
-
runner();
|
350
|
-
timer.id = setInterval(runner, interval);
|
351
|
-
}, interval - last);
|
352
|
-
} else {
|
353
|
-
runner();
|
354
|
-
timer.id = setInterval(runner, interval);
|
355
|
-
}
|
356
|
-
|
357
|
-
} else {
|
358
|
-
timer.id = setInterval(runner, interval);
|
359
|
-
}
|
360
|
-
},
|
361
|
-
|
362
|
-
// Stop timer from `every` method by it’s ID.
|
363
|
-
_stop: function (id) {
|
364
|
-
var timer = self._timers[id];
|
365
|
-
clearInterval(timer.id);
|
366
|
-
clearTimeout(timer.delay);
|
367
|
-
delete timer.id;
|
368
|
-
delete timer.delay;
|
369
|
-
},
|
370
|
-
|
371
|
-
// Listener for `visibilitychange` event.
|
372
|
-
_stopRun: function (event) {
|
373
|
-
var isHidden = self.hidden(),
|
374
|
-
wasHidden = self._wasHidden;
|
375
|
-
|
376
|
-
if ( (isHidden && !wasHidden) || (!isHidden && wasHidden) ) {
|
377
|
-
for ( var i in self._timers ) {
|
378
|
-
self._stop(i);
|
379
|
-
self._run(i, !isHidden);
|
380
|
-
}
|
381
|
-
}
|
382
|
-
}
|
383
|
-
|
384
|
-
};
|
385
|
-
|
386
|
-
for ( var prop in timers ) {
|
387
|
-
Visibility[prop] = timers[prop];
|
388
|
-
}
|
389
|
-
|
390
|
-
})();
|