visibilityjs 0.6.2 → 1.0.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.
- 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
|