visibility 0.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ == 0.2 (Sputnik 2, Laika)
2
+ * Rename support() to isSupported() and notPrerender() to afterPrerendering().
3
+ * Fix IE 6 and 7 support.
4
+ * Documentation fixes by Peter Zotov.
5
+
6
+ == 0.1 (Sputnik 1, the first)
7
+ * initial release.
data/README.md CHANGED
@@ -1,164 +1,170 @@
1
- # Visibility.js – sugar for Page Visibility API
1
+ # Visibility.js – a wrapper for the Page Visibility API
2
2
 
3
- Visibility.js allow you to know, that your web page is visible to the user or
4
- hidden in background tab or prerendering. It allow you to depend JS logic on
5
- page visibility state and save browser performance (disable unnecessary timers
6
- and AJAX requests) or create careful UI (for example, you can stop video or
7
- slideshow, when user switch tab to answer for urgent email).
3
+ Visibility.js allow you to determine whether your web page is visible to an
4
+ user, is hidden in background tab or is prerendering. It allows you use the page
5
+ visibility state in JavaScript logic and improve browser performance by
6
+ disabling unnecessary timers and AJAX requests, or improve user interface
7
+ experience (for example, by stopping video playback or slideshow when user
8
+ switches to another browser tab).
8
9
 
9
- Also you can detect, that browser just [prerendering] page, and don’t count
10
- visitor (before user will not really click on estimated link) or run heavy
11
- calculations (which can disable prerendering).
10
+ Moreover, you can detect if the browser is just [prerendering] the page while
11
+ the user has not still opened the link, and don’t count this as a visit in your
12
+ analytics module, or do not run heavy calculations or other actions which will
13
+ disable the prerendering.
12
14
 
13
- This library is wrap under [Page Visibility API]. It fix problems with different
14
- vendor prefixes and add high-level useful functions.
15
+ This library is a wrapper of the [Page Visibility API]. It eases usage of the
16
+ API by hiding vendor-specific property prefixes and adding some high-level
17
+ functions.
15
18
 
16
- You don’t need to check Page Visibility API support in browser for common cases,
17
- because library without API support will just assume, that page is always
18
- visible and your logic will be work correctly.
19
+ In most cases you don’t need to check whether the Page Visibility API is
20
+ actually supported in the browser as, if it does not, the library will just
21
+ assume that the page is visible all the time, and your logic will still work
22
+ correctly, albeit less effective in some cases.
19
23
 
20
24
  [Page Visibility API]: http://www.w3.org/TR/2011/WD-page-visibility-20110602/
21
25
  [prerendering]: http://code.google.com/chrome/whitepapers/prerender.html
22
26
 
23
27
  ## States
24
28
 
25
- Now Page Visibility API support 3 visibility states:
29
+ Currently the Page Visibility API supports three visibility states:
26
30
 
27
- * `visible` user open page and work with it.
28
- * `hidden` user switch to another tab or minimize browser window.
29
- * `prerender` browser just prerendering estimated next page to
30
- instantly open it.
31
+ * `visible`: user has opened the page and works within it.
32
+ * `hidden`: user has switched to another tab or minimized browser window.
33
+ * `prerender`: browser is just prerendering a page which may possibly be opened
34
+ by the user to make the apparent loading time lesser.
31
35
 
32
36
  ## Timers
33
37
 
34
- The main user case is to run some timers only, when content is visible to user.
35
- For example, show countdown animation.
38
+ The main use case for this library is to enable some of the times only when
39
+ content is visible to the user, i.e. the ones animating a countdown animation.
36
40
 
37
- `Visibility.every(interval, callback)` is a analog of
38
- `setInterval(callback, interval)`, but call `callback` every `interval` ms only
39
- if page is visible. For example, let create countdown:
41
+ `Visibility.every(interval, callback)` is similar to
42
+ `setInterval(callback, interval)`, but calls `callback` every `interval` ms only
43
+ if the page is visible. For example, let’s create a countdown timer:
40
44
 
41
45
  ```js
42
- Visibility.every(1000, function() {
46
+ Visibility.every(1000, function () {
43
47
  updateCountdownAnimation();
44
48
  });
45
49
  ```
46
50
 
47
- You can set in second argument another interval, which will be used, when page
48
- is hidden. For example, lets check inbox updates every 1 minute for visible
49
- page and every 5 minutes for hidden:
51
+ You can provide an additional interval which will be used when the page
52
+ is hidden. In next example, a check for inbox updates will be run every 1 minute
53
+ for a visible page and every 5 minutes for a hidden one:
50
54
 
51
55
  ```js
52
56
  var minute = 60 * 1000;
53
- Visibility.every(minute, 5 * minute, function() {
54
- checkNewMails();
57
+ Visibility.every(minute, 5 * minute, function () {
58
+ checkForEmail();
55
59
  });
56
60
  ```
57
61
 
58
- Note, that callback will be execute also on every state changing from hidden to
59
- visible (to update old content).
62
+ Note that the callback will also be executed on every `hidden`->`visible` state
63
+ change to update old contents.
60
64
 
61
- You can add some really useful syntax sugar for interval formats, if you include
62
- [jQuery Chrono plugin] *before* Visibility.js:
65
+ A syntactic sugar for specifying time intervals is supported when
66
+ [jQuery Chrono plugin] is included before Visibility.js. It can be used like
67
+ this:
63
68
 
64
69
  ```js
65
- Visibility.every('minute', '5 minutes', function() {
70
+ Visibility.every('minute', '5 minutes', function () {
66
71
  checkNewMails();
67
72
  });
68
73
  ```
69
74
 
70
- `Visibility.every` return timer ID. It is **not** same ID, that return
71
- `clearInterval`, so you must use only `Visibility.stop(id)` to stop timer:
75
+ `Visibility.every` returns a timer identifier, much like the `setTimeout`
76
+ function. It cannot be passed to `clearInterval`, through, and you should use
77
+ `Visibility.stop(id)` to stop the timer.
72
78
 
73
79
  ```js
74
- slideshow = Visibility.every(5 * 1000, function() {
75
- changeSlide();
80
+ slideshow = Visibility.every(5 * 1000, function () {
81
+ nextSlide();
76
82
  });
77
83
 
78
- $('.stopSlideshow').click(function() {
84
+ $('.stopSlideshow').click(function () {
79
85
  Visibility.stop(slideshow);
80
86
  });
81
87
  ```
82
88
 
83
- If browser doesn’t support Page Visibility API, `Visibility.every` will be
84
- just full analog of `setInterval` and just run `callback` every `interval` ms
85
- for visible and hidden pages.
89
+ If the browser does not support the Page Visibility API, `Visibility.every` will
90
+ fall back to `setInterval`, and `callback` will be run every `interval` ms for
91
+ both the hidden and visible pages.
86
92
 
87
93
  [jQuery Chrono plugin]: https://github.com/avk/jQuery-Chrono
88
94
 
89
95
  ## Initializers
90
96
 
91
- Another common user case is when we need to check visibility state and wait for
92
- some value.
97
+ In another common use case you need to execute some actions upon a switch to
98
+ particular visibility state.
93
99
 
94
- ### Wait until state will be visible
100
+ ### Waiting until the page becomes visible
95
101
 
96
- `Visibility.onVisible(callback)` check current state. If it visible now, it
97
- will run `callback`, else it will wait until state changes to visible and then
98
- run `callback`.
102
+ `Visibility.onVisible(callback)` checks current state of the page. If it is
103
+ visible now, it will run `callback`, otherwise it will wait until state changes
104
+ to `visible`, and then run `callback`.
99
105
 
100
- For example, lets show new notification animation only when page is visible
101
- (so if user open page directly in background tab, animation will be wait until
102
- user open tab):
106
+ For example, let’s show an animated notification only when the page is visible,
107
+ so if an user opens a page in the background, the animation will delay until
108
+ the page becomes visible, i.e. until the user has switched to a tab with
109
+ the page:
103
110
 
104
111
  ```js
105
- Visibility.onVisible(function() {
112
+ Visibility.onVisible(function () {
106
113
  Notification.animateNotice("Hello");
107
114
  });
108
115
  ```
109
116
 
110
- If browser doesn’t support Page Visibility API, `Visibility.onVisible` will run
111
- `callback` at once.
117
+ If a browser doesn’t support Page Visibility API, `Visibility.onVisible` will
118
+ run the `callback` immediately.
112
119
 
113
- ### Wait until state will be not prerender
120
+ ### Wait until the page is opened after prerendering
114
121
 
115
- Web developer can say by Prerender API, that user is likely to open next link
116
- (for example, when a user is reading a multi-page article). So browser will
117
- fetch and render this link and when user click link, he will see content
118
- instantly.
122
+ A web developer can hint a browser (using Prerendering API) that an user is
123
+ likely to click on some link (i.e. on a "Next" link in a multi-page article),
124
+ and the browser then may prefetch and prerender the page, so that the user will
125
+ not wait after actually going via the like.
119
126
 
120
- But when browser will prerendering page, you may decide that is really
121
- (not probably) visitor. Also, browser will turn off prerendering, if you have
122
- heavy computation or video/audio tags on page. So it will be better,
123
- if your JS will not run some code in prerendering and wait until
124
- user really open link.
127
+ But you may not want to count the browser prerendering a page as a visitor in
128
+ your analytics system. Moreover, the browser will disable prerendering if you
129
+ will try to do heavy computations or use audio/video tags on the page. So, you
130
+ may decide to not run parts of the code while prerendering and wait until the
131
+ user actually opens the link.
125
132
 
126
- You can use `Visibility.notPrerender(callback)` for this cases. For example,
127
- lets count statistics only for real visitor, not for prerendering:
133
+ You can use `Visibility.afterPrerendering(callback)` in this cases. For example,
134
+ this code will only take real visitors (and not page prerenderings) into
135
+ account:
128
136
 
129
137
  ```js
130
- Visibility.notPrerender(function() {
138
+ Visibility.afterPrerendering(function () {
131
139
  Statistics.countVisitor();
132
140
  });
133
141
  ```
134
142
 
135
- Or we can add audio and video tags or start heavy computation in
136
- non-prerendering states.
137
-
138
- If browser doesn’t support Page Visibility API, `Visibility.notPrerender` will
139
- run `callback` at once.
143
+ If the browser doesn’t support Page Visibility API,
144
+ `Visibility.afterPrerendering` will run `callback` immediately.
140
145
 
141
- ## Low-level tools
146
+ ## Low-level API
142
147
 
143
- For some special cases you can need more low-level methods. For example, if you
144
- want to count background and foreground time of page using.
148
+ In some cases you may need more low-level methods. For example, you may want to
149
+ count the time user has viewed the page in foreground and time it has stayed in
150
+ background.
145
151
 
146
- `Visibility.support()` will return `true`, if browser support
152
+ `Visibility.isSupported()` will return `true` if browser supports the
147
153
  Page Visibility API:
148
154
 
149
155
  ```js
150
- if ( Visibility.support() ) {
156
+ if( Visibility.isSupported() ) {
151
157
  Statistics.startTrackingVisibility();
152
158
  }
153
159
  ```
154
160
 
155
- `Visibility.state()` will return string with visibility state name. States can
156
- be extend in future, so in common cases use more simpler and general
157
- `Visibility.hidden()`, that will return `true`, if page is hidden by any reason.
158
- For example, in prerendering `Visibility.state()` will return `"prerender"`, but
159
- `Visibility.hidden()` will return `true`.
161
+ `Visibility.state()` will return a string with visibility state. More states
162
+ can be added in the future, so for most cases a simpler `Visibility.hidden()`
163
+ method can be used. It will return `true` if the page is hidden by any reason.
164
+ For example, while prerendering, `Visibility.state()` will return `"prerender"`,
165
+ but `Visibility.hidden()` will return `true`.
160
166
 
161
- Lets collect in what state user open our page:
167
+ This code will aid in collecting page visibility statistics:
162
168
 
163
169
  ```js
164
170
  $(document).load(function () {
@@ -173,8 +179,8 @@ $(document).load(function () {
173
179
  });
174
180
  ```
175
181
 
176
- Or lets enable auto-playing only when page opening in current tab
177
- (not, when user open page in background tab):
182
+ And this example will only enable auto-playing when the page is opening as a
183
+ visible tab (not a background one):
178
184
 
179
185
  ```js
180
186
  $(document).load(function () {
@@ -186,29 +192,29 @@ $(document).load(function () {
186
192
  });
187
193
  ```
188
194
 
189
- By `Visibility.change(callback)` you can listen visibility state changing event.
190
- First argument in callback will be event object, second will be state name.
195
+ Using `Visibility.change(callback)` you can listen to visibility state changing
196
+ events. The `callback` takes 2 arguments: an event object and a state name.
191
197
 
192
- Lets collect visibility changes to statistics, how user use our site:
198
+ Let’s collect some statistics with this evented approach:
193
199
 
194
200
  ```js
195
- Visibility.change(function(e, state) {
201
+ Visibility.change(function (e, state) {
196
202
  Statistics.visibilityChange(state);
197
203
  });
198
204
  ```
199
205
 
200
- ## Install
206
+ ## Installing
201
207
 
202
208
  ### Rails 3.1
203
209
 
204
- In Rails 3.1 (or another project with Sprockets 2) just add `visibility` to
205
- `Gemfile`:
210
+ In Rails 3.1 (or another framework with Sprockets 2) just add `visibility` gem
211
+ to `Gemfile`:
206
212
 
207
213
  ```ruby
208
214
  gem 'visibility'
209
215
  ```
210
216
 
211
- and add require to `app/assets/javascripts/application.js.coffee`:
217
+ and require it in `app/assets/javascripts/application.js.coffee`:
212
218
 
213
219
  ```coffee
214
220
  #= require "visibility"
@@ -216,8 +222,9 @@ and add require to `app/assets/javascripts/application.js.coffee`:
216
222
 
217
223
  ### Jammit
218
224
 
219
- If you use Jammit or another package manager just copy `lib/visibility.js` to
220
- `public/javascripts/lib` in your project and add library to `config/assets.yml`:
225
+ If you use Jammit or another package manager, you’ll need to copy
226
+ `lib/visibility.js` to `public/javascripts/lib` in your project and add the
227
+ library to `config/assets.yml`:
221
228
 
222
229
  ```yaml
223
230
  javascripts:
@@ -227,21 +234,22 @@ javascripts:
227
234
 
228
235
  ### Other
229
236
 
230
- If you didn’t use Rails 3.1 or assets packaging manager you can use already
231
- minimized version of library at `lib/visibility.min.js`.
237
+ If you don’t use Rails 3.1 or assets packaging manager you can use an already
238
+ minified version of the library, located in repository as
239
+ `lib/visibility.min.js`.
232
240
 
233
241
  ## Contributing
234
242
 
235
- To run project tests and minimize source you must have Ruby and Bundler.
236
- For example, on Ubuntu:
243
+ To run project tests and minimize source you’ll need to have Ruby and Bundler
244
+ installed. For example, in a Debian-based (e.g. Ubuntu) environment:
237
245
 
238
246
  ```
239
247
  sudo apt-get install ruby rubygems
240
248
  sudo gem install bundler
241
249
  ```
242
250
 
243
- Next you need install Jasmine, UglifyJS and other dependencies by Bundler.
244
- Run in project root:
251
+ Then, you will need to install Jasmine, UglifyJS and other dependencies with
252
+ Bundler. Run in root of the project repository:
245
253
 
246
254
  ```
247
255
  bundle install --path=.bundle
@@ -253,7 +261,7 @@ That’s all. To run tests, start server and open <http://localhost:8888/>:
253
261
  bundle exec rake server
254
262
  ```
255
263
 
256
- Before commit minimize project source:
264
+ Minimize the source before commiting:
257
265
 
258
266
  ```
259
267
  bundle exec rake min
@@ -49,9 +49,9 @@
49
49
  // visible.
50
50
  _onVisibleCallbacks: [],
51
51
 
52
- // Callbacks from `notPrerender` method, that wait when visibility state
53
- // change from “prerender”.
54
- _notPrerenderCallbacks: [],
52
+ // Callbacks from `afterPrerendering` method, that wait when visibility
53
+ // state change from “prerender”.
54
+ _afterPrerenderingCallbacks: [],
55
55
 
56
56
  // Last timer number.
57
57
  _lastTimer: 0,
@@ -131,10 +131,11 @@
131
131
  }
132
132
 
133
133
  if ( 'prerender' != this.state() ) {
134
- for ( var i = 0; i < this._notPrerenderCallbacks.length; i++ ) {
135
- this._notPrerenderCallbacks[i]();
134
+ var after = this._afterPrerenderingCallbacks.length
135
+ for ( var i = 0; i < after; i++ ) {
136
+ this._afterPrerenderingCallbacks[i]();
136
137
  }
137
- this._notPrerenderCallbacks = [];
138
+ this._afterPrerenderingCallbacks = [];
138
139
  }
139
140
 
140
141
  this._hiddenBefore = isHidden;
@@ -199,7 +200,7 @@
199
200
  timer.intervalID = this._setInterval(timer.callback, interval);
200
201
  },
201
202
 
202
- // Stop timer from `every` method by it's ID.
203
+ // Stop timer from `every` method by its ID.
203
204
  _stopTimer: function (id) {
204
205
  var timer = this._timers[id];
205
206
  clearInterval(timer.intervalID);
@@ -208,13 +209,13 @@
208
209
 
209
210
  // Return true if browser support Page Visibility API.
210
211
  //
211
- // if ( Visibility.support() ) {
212
+ // if ( Visibility.isSupported() ) {
212
213
  // Statistics.startTrackingVisibility();
213
214
  // Visibility.change(function(e, state)) {
214
215
  // Statistics.trackVisibility(state);
215
216
  // });
216
217
  // }
217
- support: function () {
218
+ isSupported: function () {
218
219
  return defined(this._prefix());
219
220
  },
220
221
 
@@ -226,7 +227,7 @@
226
227
  //
227
228
  // It is just proxy to `document.hidden`, but use vendor prefix.
228
229
  hidden: function () {
229
- if ( !this.support() ) {
230
+ if ( !this.isSupported() ) {
230
231
  return false;
231
232
  }
232
233
  return this._prop('hidden');
@@ -245,7 +246,7 @@
245
246
  // It is just proxy to `document.visibilityState`, but use
246
247
  // vendor prefix.
247
248
  state: function () {
248
- if ( !this.support() ) {
249
+ if ( !this.isSupported() ) {
249
250
  return 'visible';
250
251
  }
251
252
  return this._prop('visibilityState');
@@ -264,7 +265,7 @@
264
265
  //
265
266
  // It is just proxy to `visibilitychange` event, but use vendor prefix.
266
267
  change: function (callback) {
267
- if ( !this.support() ) {
268
+ if ( !this.isSupported() ) {
268
269
  return false;
269
270
  }
270
271
  this._changeCallbacks.push(callback);
@@ -282,7 +283,7 @@
282
283
  // Notification.animateNotice("Hello");
283
284
  // });
284
285
  onVisible: function (callback) {
285
- if ( !this.support() || !this.hidden() ) {
286
+ if ( !this.isSupported() || !this.hidden() ) {
286
287
  callback();
287
288
  return true;
288
289
  }
@@ -295,15 +296,15 @@
295
296
  // If Page Visibility API doesn’t supported, it will call `callback`
296
297
  // immediately.
297
298
  //
298
- // Visibility.notPrerender(function() {
299
+ // Visibility.afterPrerendering(function () {
299
300
  // Statistics.countVisitor();
300
301
  // });
301
- notPrerender: function (callback) {
302
- if ( !this.support() || 'prerender' != this.state() ) {
302
+ afterPrerendering: function (callback) {
303
+ if ( !this.isSupported() || 'prerender' != this.state() ) {
303
304
  callback();
304
305
  return true;
305
306
  }
306
- this._notPrerenderCallbacks.push(callback);
307
+ this._afterPrerenderingCallbacks.push(callback);
307
308
  this._setListener();
308
309
  },
309
310
 
@@ -327,7 +328,7 @@
327
328
  // It return timer ID, that you can use in `Visibility.stop(id)` to stop
328
329
  // timer (`clearInterval` analog).
329
330
  // Warning: timer ID is different from intervalID from `setInterval`,
330
- // so don't use it in `clearInterval`.
331
+ // so dont use it in `clearInterval`.
331
332
  //
332
333
  // On change state from hidden to visible timers will be execute.
333
334
  //
@@ -353,7 +354,9 @@
353
354
  callback: callback
354
355
  });
355
356
  this._runTimer(number, false);
356
- this._setListener();
357
+ if ( this.isSupported() ) {
358
+ this._setListener();
359
+ }
357
360
  return number;
358
361
  },
359
362
 
metadata CHANGED
@@ -1,12 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: visibility
3
3
  version: !ruby/object:Gem::Version
4
- hash: 9
4
+ hash: 15
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 1
9
- version: "0.1"
8
+ - 2
9
+ version: "0.2"
10
10
  platform: ruby
11
11
  authors:
12
12
  - "Andrey \xE2\x80\x9CA.I.\xE2\x80\x9D Sitnik"
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-06-20 00:00:00 +04:00
17
+ date: 2011-06-26 00:00:00 +04:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -35,7 +35,7 @@ dependencies:
35
35
  requirement: *id001
36
36
  type: :runtime
37
37
  name: sprockets
38
- description: Visibility.js allow you to depend JS logic on page visibility state and save browser performance or create careful UI.
38
+ description: Visibility.js allow you to determine whether your web page is visible to an user, is hidden in background tab or is prerendering. It allows you use the page visibility state in JavaScript logic and improve browser performance or improve user interface experience.
39
39
  email:
40
40
  - andrey@sitnik.ru
41
41
  executables: []
@@ -49,6 +49,7 @@ files:
49
49
  - vendor/assets/javascripts/visibility.js
50
50
  - LICENSE
51
51
  - README.md
52
+ - ChangeLog
52
53
  has_rdoc: true
53
54
  homepage: https://github.com/evilmartians/visibility.js
54
55
  licenses: []
@@ -82,6 +83,6 @@ rubyforge_project:
82
83
  rubygems_version: 1.3.7
83
84
  signing_key:
84
85
  specification_version: 3
85
- summary: Visibility.js allow you to know, that your web page is visible to the user or hidden in background tab or prerendering.
86
+ summary: "Visibility.js \xE2\x80\x93 a wrapper for the Page Visibility API."
86
87
  test_files: []
87
88