visibilityjs 0.6.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +4 -0
- data/README.md +41 -58
- data/lib/assets/javascripts/visibility.core.js +2 -9
- data/lib/assets/javascripts/visibility.js +5 -44
- data/lib/assets/javascripts/visibility.timers.js +3 -35
- metadata +8 -8
data/ChangeLog
CHANGED
data/README.md
CHANGED
@@ -1,42 +1,42 @@
|
|
1
|
-
# Visibility.js
|
1
|
+
# Visibility.js: a wrapper for the Page Visibility API
|
2
2
|
|
3
3
|
Visibility.js allows you to determine whether your web page is visible to a
|
4
|
-
user, is hidden in background tab or
|
5
|
-
page visibility state in JavaScript logic and improve browser performance
|
6
|
-
disabling unnecessary timers and AJAX requests, or improve user interface
|
7
|
-
experience (for
|
4
|
+
user, is hidden in background tab or is prerendering. It allows you to use
|
5
|
+
the page visibility state in JavaScript logic and improve browser performance
|
6
|
+
by disabling unnecessary timers and AJAX requests, or improve user interface
|
7
|
+
experience (for example, by stopping video playback or slideshow when user
|
8
8
|
switches to another browser tab).
|
9
9
|
|
10
10
|
Moreover, you can detect if the browser is just [prerendering] the page while
|
11
|
-
the user has not still opened the
|
11
|
+
the user has not still opened the link, and don’t count this as a visit in your
|
12
12
|
analytics module, or do not run heavy calculations or other actions which will
|
13
13
|
disable the prerendering.
|
14
14
|
|
15
|
-
This library is a wrapper of the [Page Visibility API]. It eases usage
|
16
|
-
API by hiding vendor-specific property prefixes and adding some
|
17
|
-
functions.
|
15
|
+
This library is a wrapper of the [Page Visibility API]. It eases usage
|
16
|
+
of the API by hiding vendor-specific property prefixes and adding some
|
17
|
+
high-level functions.
|
18
18
|
|
19
19
|
In most cases you don’t need to check whether the Page Visibility API is
|
20
20
|
actually supported in the browser as, if it does not, the library will just
|
21
21
|
assume that the page is visible all the time, and your logic will still work
|
22
22
|
correctly, albeit less effective in some cases.
|
23
23
|
|
24
|
-
Page Visibility API is [natively supported] by
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
Page Visibility API is [natively supported] by all browsers. For old browsers
|
25
|
+
you can use `lib/visibility.fallback.js` with focus/blur hack (note that this
|
26
|
+
hack have issue, that document become to be hidden, when browser just
|
27
|
+
lose focus, but still visible for user).
|
28
28
|
|
29
29
|
Sponsored by [Evil Martians].
|
30
30
|
|
31
|
-
[Page Visibility API]: http://www.w3.org/TR/
|
31
|
+
[Page Visibility API]: http://www.w3.org/TR/page-visibility/
|
32
32
|
[prerendering]: http://code.google.com/chrome/whitepapers/prerender.html
|
33
|
-
[
|
34
|
-
[natively supported]: http://caniuse.com/#feat=pagevisibility
|
33
|
+
[natively supported]: http://caniuse.com/pagevisibility
|
35
34
|
[Evil Martians]: http://evilmartians.com/
|
36
35
|
|
37
36
|
## Translations
|
38
37
|
|
39
|
-
Документация на русском:
|
38
|
+
Документация на русском:
|
39
|
+
[habrahabr.ru/blogs/javascript/125833/](http://habrahabr.ru/blogs/javascript/125833/)
|
40
40
|
|
41
41
|
## States
|
42
42
|
|
@@ -45,12 +45,12 @@ Currently the Page Visibility API supports three visibility states:
|
|
45
45
|
* `visible`: user has opened the page and works within it.
|
46
46
|
* `hidden`: user has switched to another tab or minimized browser window.
|
47
47
|
* `prerender`: browser is just prerendering a page which may possibly be opened
|
48
|
-
by the user to make the
|
48
|
+
by the user to make the apparent loading time lesser.
|
49
49
|
|
50
50
|
## Timers
|
51
51
|
|
52
52
|
The main use case for this library is to enable some of the times only when
|
53
|
-
content is visible to the user, i.e.
|
53
|
+
content is visible to the user, i.e. the ones animating a countdown animation.
|
54
54
|
|
55
55
|
`Visibility.every(interval, callback)` is similar to
|
56
56
|
`setInterval(callback, interval)`, but calls `callback` every `interval` ms only
|
@@ -63,7 +63,7 @@ Visibility.every(1000, function () {
|
|
63
63
|
```
|
64
64
|
|
65
65
|
You can provide an additional interval which will be used when the page
|
66
|
-
is hidden. In next example, a check for
|
66
|
+
is hidden. In next example, a check for inbox updates will be run every 1 minute
|
67
67
|
for a visible page and every 5 minutes for a hidden one:
|
68
68
|
|
69
69
|
```js
|
@@ -76,18 +76,8 @@ Visibility.every(minute, 5 * minute, function () {
|
|
76
76
|
Note that the callback will also be executed on every `hidden`->`visible` state
|
77
77
|
change to update old contents.
|
78
78
|
|
79
|
-
A syntactic sugar for specifying time intervals is supported when
|
80
|
-
[jQuery Chrono plugin] is included before Visibility.js. It can be used like
|
81
|
-
this:
|
82
|
-
|
83
|
-
```js
|
84
|
-
Visibility.every('minute', '5 minutes', function () {
|
85
|
-
checkNewMails();
|
86
|
-
});
|
87
|
-
```
|
88
|
-
|
89
79
|
`Visibility.every` returns a timer identifier, much like the `setTimeout`
|
90
|
-
function. It cannot be passed to
|
80
|
+
function. It cannot be passed to `clearInterval`, through, and you should use
|
91
81
|
`Visibility.stop(id)` to stop the timer.
|
92
82
|
|
93
83
|
```js
|
@@ -101,11 +91,9 @@ $('.stopSlideshow').click(function () {
|
|
101
91
|
```
|
102
92
|
|
103
93
|
If the browser does not support the Page Visibility API, `Visibility.every` will
|
104
|
-
fall back to `setInterval`, and
|
94
|
+
fall back to `setInterval`, and `callback` will be run every `interval` ms for
|
105
95
|
both the hidden and visible pages.
|
106
96
|
|
107
|
-
[jQuery Chrono plugin]: https://github.com/avk/jQuery-Chrono
|
108
|
-
|
109
97
|
## Initializers
|
110
98
|
|
111
99
|
In another common use case you need to execute some actions upon a switch to
|
@@ -118,9 +106,9 @@ visible now, it will run `callback`, otherwise it will wait until state changes
|
|
118
106
|
to `visible`, and then run `callback`.
|
119
107
|
|
120
108
|
For example, let’s show an animated notification only when the page is visible,
|
121
|
-
so if an user opens a page in
|
122
|
-
the page becomes visible, i.e. until the user has switched
|
123
|
-
the
|
109
|
+
so if an user opens a page in the background, the animation will delay until
|
110
|
+
the page becomes visible, i.e. until the user has switched
|
111
|
+
to a tab with the page:
|
124
112
|
|
125
113
|
```js
|
126
114
|
Visibility.onVisible(function () {
|
@@ -128,14 +116,14 @@ Visibility.onVisible(function () {
|
|
128
116
|
});
|
129
117
|
```
|
130
118
|
|
131
|
-
If a browser doesn’t support Page Visibility API, `Visibility.onVisible`
|
132
|
-
run the `callback` immediately.
|
119
|
+
If a browser doesn’t support Page Visibility API, `Visibility.onVisible`
|
120
|
+
will run the `callback` immediately.
|
133
121
|
|
134
122
|
### Wait until the page is opened after prerendering
|
135
123
|
|
136
|
-
A web developer can hint a browser (using Prerendering API) that an user
|
137
|
-
likely to click on some link (i.e.
|
138
|
-
and the browser then may prefetch and prerender the page, so
|
124
|
+
A web developer can hint a browser (using Prerendering API) that an user
|
125
|
+
is likely to click on some link (i.e. on a “Next” link in a multi-page article),
|
126
|
+
and the browser then may prefetch and prerender the page, so that the user will
|
139
127
|
not wait after actually going via the like.
|
140
128
|
|
141
129
|
But you may not want to count the browser prerendering a page as a visitor in
|
@@ -160,7 +148,7 @@ If the browser doesn’t support Page Visibility API,
|
|
160
148
|
## Low-level API
|
161
149
|
|
162
150
|
In some cases you may need more low-level methods. For example, you may want to
|
163
|
-
count the time user
|
151
|
+
count the time user has viewed the page in foreground and time it has stayed in
|
164
152
|
background.
|
165
153
|
|
166
154
|
`Visibility.isSupported()` will return `true` if browser supports the
|
@@ -174,9 +162,9 @@ if( Visibility.isSupported() ) {
|
|
174
162
|
|
175
163
|
`Visibility.state()` will return a string with visibility state. More states
|
176
164
|
can be added in the future, so for most cases a simpler `Visibility.hidden()`
|
177
|
-
method can be used. It will return `true` if the page is
|
165
|
+
method can be used. It will return `true` if the page is hidden by any reason.
|
178
166
|
For example, while prerendering, `Visibility.state()` will return `"prerender"`,
|
179
|
-
but
|
167
|
+
but `Visibility.hidden()` will return `true`.
|
180
168
|
|
181
169
|
This code will aid in collecting page visibility statistics:
|
182
170
|
|
@@ -207,7 +195,7 @@ $(document).load(function () {
|
|
207
195
|
```
|
208
196
|
|
209
197
|
Using `Visibility.change(callback)` you can listen to visibility state changing
|
210
|
-
events. The `callback` takes 2
|
198
|
+
events. The `callback` takes 2 arguments: an event object and a state name.
|
211
199
|
|
212
200
|
Let’s collect some statistics with this evented approach:
|
213
201
|
|
@@ -233,7 +221,7 @@ VideoPlayer.onFinish(function () {
|
|
233
221
|
```
|
234
222
|
|
235
223
|
Methods `onVisible` and `afterPrerendering` will also return listener ID,
|
236
|
-
if
|
224
|
+
if they wait visibility state changes. If they execute callback immediately,
|
237
225
|
they return `true` if Page Visibility API is supported and `false`
|
238
226
|
if they can’t detect visibility state.
|
239
227
|
|
@@ -294,20 +282,17 @@ For Ruby on Rails you can use gem for Assets Pipeline.
|
|
294
282
|
|
295
283
|
### CDN
|
296
284
|
|
297
|
-
If you don’t use any assets packaging manager use [
|
285
|
+
If you don’t use any assets packaging manager use [cdnjs](http://cdnjs.com/).
|
286
|
+
Add to your site:
|
298
287
|
|
299
288
|
```html
|
300
|
-
<script src="//cdnjs.cloudflare.com/ajax/libs/visibility.js/0.
|
289
|
+
<script src="//cdnjs.cloudflare.com/ajax/libs/visibility.js/1.0.0/visibility.min.js"></script>
|
301
290
|
```
|
302
291
|
|
303
|
-
[CDNJS]: http://cdnjs.com/
|
304
|
-
|
305
292
|
### Other
|
306
293
|
|
307
294
|
If you need just a files, you can take already minified packages from
|
308
|
-
[github.com/ai/visibility.js/
|
309
|
-
|
310
|
-
[github.com/ai/visibility.js/downloads]: https://github.com/ai/visibility.js/downloads
|
295
|
+
[github.com/ai/visibility.js/releases](https://github.com/ai/visibility.js/releases).
|
311
296
|
|
312
297
|
## Contributing
|
313
298
|
|
@@ -326,7 +311,7 @@ If you need just a files, you can take already minified packages from
|
|
326
311
|
3. Run all tests:
|
327
312
|
|
328
313
|
```sh
|
329
|
-
|
314
|
+
npm test
|
330
315
|
```
|
331
316
|
|
332
317
|
4. Run test server, to check code in real browsers:
|
@@ -335,8 +320,6 @@ If you need just a files, you can take already minified packages from
|
|
335
320
|
./node_modules/.bin/cake server
|
336
321
|
```
|
337
322
|
|
338
|
-
5. Open tests in browser: [localhost:8000].
|
323
|
+
5. Open tests in browser: [localhost:8000](http://localhost:8000).
|
339
324
|
6. Also you can see real usage example in integration test
|
340
325
|
`test/integration.html`.
|
341
|
-
|
342
|
-
[localhost:8000]: http://localhost:8000
|
@@ -159,9 +159,6 @@
|
|
159
159
|
// Link to document object to change it in tests.
|
160
160
|
_doc: window.document,
|
161
161
|
|
162
|
-
// Vendor prefixes to create event and properties names.
|
163
|
-
_prefixes: ['webkit', 'moz'],
|
164
|
-
|
165
162
|
// Vendor prefix cached by `_prefix` function.
|
166
163
|
_chechedPrefix: null,
|
167
164
|
|
@@ -191,12 +188,8 @@
|
|
191
188
|
if ( defined(self._doc.visibilityState) ) {
|
192
189
|
return self._chechedPrefix = '';
|
193
190
|
}
|
194
|
-
|
195
|
-
|
196
|
-
name = self._prefixes[i] + 'VisibilityState';
|
197
|
-
if ( defined(self._doc[name]) ) {
|
198
|
-
return self._chechedPrefix = self._prefixes[i];
|
199
|
-
}
|
191
|
+
if ( defined(self._doc.webkitVisibilityState) ) {
|
192
|
+
return self._chechedPrefix = 'webkit';
|
200
193
|
}
|
201
194
|
},
|
202
195
|
|
@@ -159,9 +159,6 @@
|
|
159
159
|
// Link to document object to change it in tests.
|
160
160
|
_doc: window.document,
|
161
161
|
|
162
|
-
// Vendor prefixes to create event and properties names.
|
163
|
-
_prefixes: ['webkit', 'moz'],
|
164
|
-
|
165
162
|
// Vendor prefix cached by `_prefix` function.
|
166
163
|
_chechedPrefix: null,
|
167
164
|
|
@@ -191,12 +188,8 @@
|
|
191
188
|
if ( defined(self._doc.visibilityState) ) {
|
192
189
|
return self._chechedPrefix = '';
|
193
190
|
}
|
194
|
-
|
195
|
-
|
196
|
-
name = self._prefixes[i] + 'VisibilityState';
|
197
|
-
if ( defined(self._doc[name]) ) {
|
198
|
-
return self._chechedPrefix = self._prefixes[i];
|
199
|
-
}
|
191
|
+
if ( defined(self._doc.webkitVisibilityState) ) {
|
192
|
+
return self._chechedPrefix = 'webkit';
|
200
193
|
}
|
201
194
|
},
|
202
195
|
|
@@ -279,16 +272,6 @@
|
|
279
272
|
// so don’t use it in `clearInterval`.
|
280
273
|
//
|
281
274
|
// On change state from hidden to visible timers will be execute.
|
282
|
-
//
|
283
|
-
// If you include jQuery Chrono plugin before Visibility.js, you could
|
284
|
-
// use Chrono’s syntax sugar in interval arguments:
|
285
|
-
//
|
286
|
-
// Visibility.every('second', function () {
|
287
|
-
// updateCountdown();
|
288
|
-
// });
|
289
|
-
// Visibility.every('1 minute', '5 minutes', function () {
|
290
|
-
// checkNewMails();
|
291
|
-
// });
|
292
275
|
every: function (interval, hiddenInterval, callback) {
|
293
276
|
self._initTimers();
|
294
277
|
|
@@ -345,38 +328,16 @@
|
|
345
328
|
}
|
346
329
|
self._timersInitialized = true;
|
347
330
|
|
348
|
-
if ( defined(window.jQuery) && defined(jQuery.every) ) {
|
349
|
-
self._setInterval = self._chronoInterval;
|
350
|
-
} else {
|
351
|
-
self._setInterval = self._originalInterval;
|
352
|
-
}
|
353
331
|
self.change(function () {
|
354
332
|
self._timersStopRun()
|
355
333
|
});
|
356
334
|
},
|
357
335
|
|
358
|
-
// Set interval directly by `setInterval` function without any syntax
|
359
|
-
// sugar.
|
360
|
-
_originalInterval: function (callback, interval) {
|
361
|
-
return setInterval(callback, interval);
|
362
|
-
},
|
363
|
-
|
364
|
-
// Set interval by jQuery Chrono plugin. Add syntax sugar to `interval`
|
365
|
-
// and `hiddenInterval` arguments, such as "1 second" and others.
|
366
|
-
//
|
367
|
-
// It will be automatically set to `_setInterval` on loading if
|
368
|
-
// you include jQuery Chrono plugin before Visibility.js.
|
369
|
-
_chronoInterval: function (callback, internal) {
|
370
|
-
return jQuery.every(internal, callback);
|
371
|
-
},
|
372
|
-
|
373
336
|
// Set interval by `setInterval`. Allow to change function for tests or
|
374
337
|
// syntax sugar in `interval` arguments.
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
// before Visibility.js.
|
379
|
-
_setInterval: null,
|
338
|
+
_setInterval: function (callback, interval) {
|
339
|
+
return setInterval(callback, interval);
|
340
|
+
},
|
380
341
|
|
381
342
|
// Try to run timer from every method by it’s ID. It will be use
|
382
343
|
// `interval` or `hiddenInterval` depending on visibility state.
|
@@ -50,16 +50,6 @@
|
|
50
50
|
// so don’t use it in `clearInterval`.
|
51
51
|
//
|
52
52
|
// On change state from hidden to visible timers will be execute.
|
53
|
-
//
|
54
|
-
// If you include jQuery Chrono plugin before Visibility.js, you could
|
55
|
-
// use Chrono’s syntax sugar in interval arguments:
|
56
|
-
//
|
57
|
-
// Visibility.every('second', function () {
|
58
|
-
// updateCountdown();
|
59
|
-
// });
|
60
|
-
// Visibility.every('1 minute', '5 minutes', function () {
|
61
|
-
// checkNewMails();
|
62
|
-
// });
|
63
53
|
every: function (interval, hiddenInterval, callback) {
|
64
54
|
self._initTimers();
|
65
55
|
|
@@ -116,38 +106,16 @@
|
|
116
106
|
}
|
117
107
|
self._timersInitialized = true;
|
118
108
|
|
119
|
-
if ( defined(window.jQuery) && defined(jQuery.every) ) {
|
120
|
-
self._setInterval = self._chronoInterval;
|
121
|
-
} else {
|
122
|
-
self._setInterval = self._originalInterval;
|
123
|
-
}
|
124
109
|
self.change(function () {
|
125
110
|
self._timersStopRun()
|
126
111
|
});
|
127
112
|
},
|
128
113
|
|
129
|
-
// Set interval directly by `setInterval` function without any syntax
|
130
|
-
// sugar.
|
131
|
-
_originalInterval: function (callback, interval) {
|
132
|
-
return setInterval(callback, interval);
|
133
|
-
},
|
134
|
-
|
135
|
-
// Set interval by jQuery Chrono plugin. Add syntax sugar to `interval`
|
136
|
-
// and `hiddenInterval` arguments, such as "1 second" and others.
|
137
|
-
//
|
138
|
-
// It will be automatically set to `_setInterval` on loading if
|
139
|
-
// you include jQuery Chrono plugin before Visibility.js.
|
140
|
-
_chronoInterval: function (callback, internal) {
|
141
|
-
return jQuery.every(internal, callback);
|
142
|
-
},
|
143
|
-
|
144
114
|
// Set interval by `setInterval`. Allow to change function for tests or
|
145
115
|
// syntax sugar in `interval` arguments.
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
// before Visibility.js.
|
150
|
-
_setInterval: null,
|
116
|
+
_setInterval: function (callback, interval) {
|
117
|
+
return setInterval(callback, interval);
|
118
|
+
},
|
151
119
|
|
152
120
|
// Try to run timer from every method by it’s ID. It will be use
|
153
121
|
// `interval` or `hiddenInterval` depending on visibility state.
|
metadata
CHANGED
@@ -1,32 +1,32 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: visibilityjs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
4
5
|
prerelease:
|
5
|
-
version: 0.6.2
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Andrey "A.I" Sitnik
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-08-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
type: :runtime
|
16
15
|
name: sprockets
|
17
|
-
prerelease: false
|
18
16
|
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
19
18
|
requirements:
|
20
19
|
- - ! '>='
|
21
20
|
- !ruby/object:Gem::Version
|
22
21
|
version: '2'
|
23
|
-
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
25
26
|
requirements:
|
26
27
|
- - ! '>='
|
27
28
|
- !ruby/object:Gem::Version
|
28
29
|
version: '2'
|
29
|
-
none: false
|
30
30
|
description: Visibility.js allow you to determine whether your web page is visible
|
31
31
|
to an user, is hidden in background tab or is prerendering. It allows you use the
|
32
32
|
page visibility state in JavaScript logic and improve browser performance or improve
|
@@ -55,17 +55,17 @@ rdoc_options: []
|
|
55
55
|
require_paths:
|
56
56
|
- lib
|
57
57
|
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
58
59
|
requirements:
|
59
60
|
- - ! '>='
|
60
61
|
- !ruby/object:Gem::Version
|
61
62
|
version: '0'
|
62
|
-
none: false
|
63
63
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
64
65
|
requirements:
|
65
66
|
- - ! '>='
|
66
67
|
- !ruby/object:Gem::Version
|
67
68
|
version: '0'
|
68
|
-
none: false
|
69
69
|
requirements: []
|
70
70
|
rubyforge_project:
|
71
71
|
rubygems_version: 1.8.23
|