diff options
author | Thomas Steur <tsteur@users.noreply.github.com> | 2014-11-27 22:32:05 +0300 |
---|---|---|
committer | Thomas Steur <tsteur@users.noreply.github.com> | 2014-11-27 22:32:05 +0300 |
commit | 68a072b5513d13e27c6d96c4085e5a184a025ab2 (patch) | |
tree | cf6b937a124549d348a4100cd49e3f9aae05f075 | |
parent | 5f5cfd27b92d3b5feacf6dab009a106d9e586075 (diff) | |
parent | 21ec2facac27f77e398679c456f3479cb9a7de12 (diff) |
Merge pull request #6625 from piwik/6545
Do not request live information in case tab is not active
-rw-r--r-- | bower.json | 3 | ||||
-rw-r--r-- | libs/bower_components/visibilityjs/.bower.json | 32 | ||||
-rw-r--r-- | libs/bower_components/visibilityjs/ChangeLog.md | 71 | ||||
-rw-r--r-- | libs/bower_components/visibilityjs/LICENSE | 20 | ||||
-rw-r--r-- | libs/bower_components/visibilityjs/README.md | 325 | ||||
-rw-r--r-- | libs/bower_components/visibilityjs/bower.json | 20 | ||||
-rw-r--r-- | libs/bower_components/visibilityjs/index.js | 1 | ||||
-rw-r--r-- | libs/bower_components/visibilityjs/lib/visibility.core.js | 191 | ||||
-rw-r--r-- | libs/bower_components/visibilityjs/lib/visibility.fallback.js | 55 | ||||
-rw-r--r-- | libs/bower_components/visibilityjs/lib/visibility.js | 4 | ||||
-rw-r--r-- | libs/bower_components/visibilityjs/lib/visibility.timers.js | 163 | ||||
-rw-r--r-- | libs/bower_components/visibilityjs/logo.svg | 19 | ||||
-rw-r--r-- | plugins/Live/Live.php | 1 | ||||
-rw-r--r-- | plugins/Live/javascripts/live.js | 56 | ||||
-rw-r--r-- | plugins/UserCountryMap/UserCountryMap.php | 1 | ||||
-rw-r--r-- | plugins/UserCountryMap/javascripts/realtime-map.js | 2 |
16 files changed, 961 insertions, 3 deletions
diff --git a/bower.json b/bower.json index b591829f43..01a17439f8 100644 --- a/bower.json +++ b/bower.json @@ -28,7 +28,8 @@ "jquery-mousewheel": "~3.1.12", "jquery-placeholder": "~2.0.8", "jquery.scrollTo": "~1.4.13", - "chroma-js": "~0.6.0" + "chroma-js": "~0.6.0", + "visibilityjs": "~1.2.1" }, "license": "GPLv3 or later", "ignore": [ diff --git a/libs/bower_components/visibilityjs/.bower.json b/libs/bower_components/visibilityjs/.bower.json new file mode 100644 index 0000000000..a284725d7d --- /dev/null +++ b/libs/bower_components/visibilityjs/.bower.json @@ -0,0 +1,32 @@ +{ + "name": "visibilityjs", + "version": "1.2.1", + "homepage": "https://github.com/ai/visibilityjs", + "authors": [ + "Andrey A.I. Sitnik <andrey@sitnik.ru>" + ], + "description": "Wrapper for the Page Visibility API", + "license": "MIT", + "main": [ + "lib/visibility.core.js", + "lib/visibility.timers.js" + ], + "ignore": [ + "package.json", + "*.gemspec", + "Cakefile", + "test", + "*.rb", + ".*" + ], + "_release": "1.2.1", + "_resolution": { + "type": "version", + "tag": "1.2.1", + "commit": "97c8ea0defd6737de911647598d6e195ff177e39" + }, + "_source": "git://github.com/ai/visibility.js.git", + "_target": "~1.2.1", + "_originalSource": "visibilityjs", + "_direct": true +}
\ No newline at end of file diff --git a/libs/bower_components/visibilityjs/ChangeLog.md b/libs/bower_components/visibilityjs/ChangeLog.md new file mode 100644 index 0000000000..5aa61359ac --- /dev/null +++ b/libs/bower_components/visibilityjs/ChangeLog.md @@ -0,0 +1,71 @@ +### 1.2.1 “Discoverer 6, again” +* Fix Bower config by Misha Ponizil. + +### 1.2.0 “Discoverer 5, spy” +* Allow to use in CommonJS. +* Release npm package. +* Reduce library size to 10 %. +* Allow to use latest version from master in Ruby Bundler. +* Method `hidden()` now always return boolean. +* Change repository URL to `github.com/ai/visibilityjs`. + +## 1.1.0 “Explorer 6, photo” +* Prevent to run timer often, that it’s interval, when visibility was changed. +* Allow to install by Bower package manager. +* Change license to MIT. +* Reduce library size. + +## 1.0.0 “Discoverer 2, stable” +* Remove jQuery.Chrono integration. +* Remove outdated Firefox prefix. + +## 0.6.2 “Pioneer 4, American Sun” +* Decrease files size (by compressible code and UnglifyJS 2). +* Remove unnecessary vendor prefixes from fallback. + +## 0.6.1 “Vanguard 2, weather” +* Remove unnecessary vendor prefixes. + +## 0.6 “Luna 1, Mechta” +* Methods onVisible and afterPrerendering return listener ID (by mcfedr). +* Fix documentation (by Erwänn Mest). + +## 0.5 “SCORE, communication” +* Split library to core and timers modules. +* Allow to unbind change listener. +* Use common logic in change(), afterPrerendering() and onVisible(). + +## 0.4.5 “Pioneer 3, closer” +* Fix gem assets directory. +* Update development dependencies. + +## 0.4.4 “Pioneer 1, deeper into space” +* Remove non-ASCII symbols from gemspec. +* Print testing URL in test task. + +## 0.4.3 “Explorer 4, short” +* Fix gemspec issue with Bundler. + +## 0.4.2 “Sputnik 3, real” +* Reorder code to show first public and common methods. +* Use node.js Cake instead of Ruby’s Rake to build tasks. +* Move to Mocha, Chai and Sinon.JS for tests. +* Move autogenerated minified to GitHub downloads. + +## 0.4.1 “Explorer 3, repeat” +* Fix documentation and gemspec. + +## 0.4 “Vanguard 1, alternative” +* Add fallback API support by focus/blur hack to all browsers. + +## 0.3 “Explorer 1, answer” +* Rename gem to visibilityjs. +* Fix gem integration with Asset Pipeline paths. + +## 0.2 “Sputnik 2, Laika” +* Rename support() to isSupported() and notPrerender() to afterPrerendering(). +* Fix IE 6 and 7 support. +* Documentation fixes by Peter Zotov. + +## 0.1 “Sputnik 1, the first” +* Initial release. diff --git a/libs/bower_components/visibilityjs/LICENSE b/libs/bower_components/visibilityjs/LICENSE new file mode 100644 index 0000000000..f92ec4cc3f --- /dev/null +++ b/libs/bower_components/visibilityjs/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright 2011 Andrey Sitnik <andrey@sitnik.ru> + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/libs/bower_components/visibilityjs/README.md b/libs/bower_components/visibilityjs/README.md new file mode 100644 index 0000000000..3f072be38f --- /dev/null +++ b/libs/bower_components/visibilityjs/README.md @@ -0,0 +1,325 @@ +# Visibility.js + +<img align="right" width="100" src="http://ai.github.io/visibilityjs/logo.svg" title="Visibility.js logo by Eugenia Tuchapets"> + +Visibility.js is a wrapper for the [Page Visibility API]. It hides vendor prefixes and adds high level functions. + +Page Visibility API allows you to determine whether your web page is visible to +a user, is hidden in background tab or is prerendering. It allows you to use +the page visibility state in JavaScript logic and improve browser performance +by disabling unnecessary timers and AJAX requests, or improve user interface +experience (for example, by stopping video playback or slideshow when user +switches to another browser tab). + +Moreover, you can detect if the browser is just [prerendering] the page while +the user has not still opened the link, and don’t count this as a visit in your +analytics module, or do not run heavy calculations or other actions which will +disable the prerendering. + +Page Visibility API is [natively supported] by all browsers. For old browsers +you can use `lib/visibility.fallback.js` with focus/blur hack (note that this +hack have issue, that document become to be hidden, when browser just +lose focus, but still visible for user). + +Sponsored by [Evil Martians]. + +[Page Visibility API]: http://www.w3.org/TR/page-visibility/ +[prerendering]: http://code.google.com/chrome/whitepapers/prerender.html +[natively supported]: http://caniuse.com/pagevisibility +[Evil Martians]: http://evilmartians.com/ + +## Translations + +Документация на русском: +[habrahabr.ru/blogs/javascript/125833/](http://habrahabr.ru/blogs/javascript/125833/) + +## States + +Currently the Page Visibility API supports three visibility states: + +* `visible`: user has opened the page and works within it. +* `hidden`: user has switched to another tab or minimized browser window. +* `prerender`: browser is just prerendering a page which may possibly be opened + by the user to make the apparent loading time lesser. + +## Timers + +The main use case for this library is to enable some of the times only when +content is visible to the user, i.e. the ones animating a countdown animation. + +`Visibility.every(interval, callback)` is similar to +`setInterval(callback, interval)`, but calls `callback` every `interval` ms only +if the page is visible. For example, let’s create a countdown timer: + +```js +Visibility.every(1000, function () { + updateCountdownAnimation(); +}); +``` + +You can provide an additional interval which will be used when the page +is hidden. In next example, a check for inbox updates will be run every 1 minute +for a visible page and every 5 minutes for a hidden one: + +```js +var minute = 60 * 1000; +Visibility.every(minute, 5 * minute, function () { + checkForEmail(); +}); +``` + +`Visibility.every` returns a timer identifier, much like the `setInterval` +function. It cannot be passed to `clearInterval`, through, and you should use +`Visibility.stop(id)` to stop the timer. + +```js +var slideshow = Visibility.every(5 * 1000, function () { + nextSlide(); +}); + +$('.stopSlideshow').click(function () { + Visibility.stop(slideshow); +}); +``` + +If the browser does not support the Page Visibility API, `Visibility.every` will +fall back to `setInterval`, and `callback` will be run every `interval` ms for +both the hidden and visible pages. + +## Initializers + +In another common use case you need to execute some actions upon a switch to +particular visibility state. + +### Waiting until the page becomes visible + +`Visibility.onVisible(callback)` checks current state of the page. If it is +visible now, it will run `callback`, otherwise it will wait until state changes +to `visible`, and then run `callback`. + +For example, let’s show an animated notification only when the page is visible, +so if an user opens a page in the background, the animation will delay until +the page becomes visible, i.e. until the user has switched +to a tab with the page: + +```js +Visibility.onVisible(function () { + startIntroAnimation(); +}); +``` + +If a browser doesn’t support Page Visibility API, `Visibility.onVisible` +will run the `callback` immediately. + +### Wait until the page is opened after prerendering + +A web developer can hint a browser (using Prerendering API) that an user +is likely to click on some link (i.e. on a “Next” link in a multi-page article), +and the browser then may prefetch and prerender the page, so that the user will +not wait after actually going via the like. + +But you may not want to count the browser prerendering a page as a visitor in +your analytics system. Moreover, the browser will disable prerendering if you +will try to do heavy computations or use audio/video tags on the page. So, you +may decide to not run parts of the code while prerendering and wait until the +user actually opens the link. + +You can use `Visibility.afterPrerendering(callback)` in this cases. For example, +this code will only take real visitors (and not page prerenderings) into +account: + +```js +Visibility.afterPrerendering(function () { + Statistics.countVisitor(); +}); +``` + +If the browser doesn’t support Page Visibility API, +`Visibility.afterPrerendering` will run `callback` immediately. + +## Low-level API + +In some cases you may need more low-level methods. For example, you may want to +count the time user has viewed the page in foreground and time it has stayed in +background. + +`Visibility.isSupported()` will return `true` if browser supports the +Page Visibility API: + +```js +if( Visibility.isSupported() ) { + Statistics.startTrackingVisibility(); +} +``` + +`Visibility.state()` will return a string with visibility state. More states +can be added in the future, so for most cases a simpler `Visibility.hidden()` +method can be used. It will return `true` if the page is hidden by any reason. +For example, while prerendering, `Visibility.state()` will return `"prerender"`, +but `Visibility.hidden()` will return `true`. + +This code will aid in collecting page visibility statistics: + +```js +$(document).load(function () { + + if ( 'hidden' == Visibility.state() ) { + Statistics.userOpenPageInBackgroundTab(); + } + if ( 'prerender' == Visibility.state() ) { + Statistics.pageIsPrerendering(); + } + +}); +``` + +And this example will only enable auto-playing when the page is opening as a +visible tab (not a background one): + +```js +$(document).load(function () { + + if ( !Visibility.hidden() ) { + VideoPlayer.play(); + } + +}); +``` + +Using `Visibility.change(callback)` you can listen to visibility state changing +events. The `callback` takes 2 arguments: an event object and a state name. + +Let’s collect some statistics with this events approach: + +```js +Visibility.change(function (e, state) { + Statistics.visibilityChange(state); +}); +``` + +Method `change` returns listener ID. You can use it to unbind listener by +`Visibility.unbind(id)`: + +```js +var listener = Visibility.change(function (e, state) { + if ( !Visibility.hidden() ) { + VideoPlayer.pause(); + } +}); + +VideoPlayer.onFinish(function () { + Visibility.unbind(listener); +}); +``` + +Methods `onVisible` and `afterPrerendering` will also return listener ID, +if they wait visibility state changes. If they execute callback immediately, +they return `true` if Page Visibility API is supported and `false` +if they can’t detect visibility state. + +```js +var listener = Visibility.onVisible(function () { + notification.takeAttention(); +}); + +notification.onOutOfDate(function () { + if ( typeof(listener) == 'number' ) { + Visibility.unbind(listener); + } +}); +``` + +## Installing + +### Packages + +Visibility.js is shipped with 4 files: + +* `visibility.core` – core module. +* `visibility.timers` – `every` and `stop` methods to set `setInterval` depend + on visibility state. +* `visibility` – `visibility.core` and `visibility.timers` together. +* `visibility.fallback` – fallback for browser without Page Visibility API. + It use document `focus`/`blur` events, so document become to be hidden, + when browser just lose focus, but still visible for user. + +### Bower + +Visibility.js is available by Bower package manager: + +``` +bower install --save visibilityjs +``` + +### Ruby on Rails + +For Ruby on Rails you can use gem for Assets Pipeline. + +1. Add `visibilityjs` gem to `Gemfile`: + + ```ruby + gem "visibilityjs" + ``` + +2. Install gems: + + ```sh + bundle install + ``` + +3. Include Visibility.js in your `application.js.coffee`: + + ```coffee + #= require visibility + ``` + + If you willn’t use `every` method, you can reduce library size by including + only core module: + + ```coffee + #= require visibility.core + ``` + +### CDN + +If you don’t use any assets packaging manager use [cdnjs](http://cdnjs.com/). +Add to your site: + +```html +<script src="//cdnjs.cloudflare.com/ajax/libs/visibility.js/1.2.0/visibility.min.js"></script> +``` + +### Other + +If you need just a files, you can take already minified packages from +[github.com/ai/visibilityjs/releases](https://github.com/ai/visibilityjs/releases). + +## Contributing + +1. To run tests you need node.js and npm. For example, in Ubuntu run: + + ```sh + sudo apt-get install nodejs npm + ``` + +2. Next install npm dependencies: + + ```sh + npm install + ``` + +3. Run all tests: + + ```sh + npm test + ``` + +4. Run test server, to check code in real browsers: + + ```sh + ./node_modules/.bin/cake server + ``` + +5. Open tests in browser: [localhost:8000](http://localhost:8000). +6. Also you can see real usage example in integration test + `test/integration.html`. diff --git a/libs/bower_components/visibilityjs/bower.json b/libs/bower_components/visibilityjs/bower.json new file mode 100644 index 0000000000..bfcf95e48f --- /dev/null +++ b/libs/bower_components/visibilityjs/bower.json @@ -0,0 +1,20 @@ +{ + "name": "visibilityjs", + "version": "1.2.1", + "homepage": "https://github.com/ai/visibilityjs", + "authors": ["Andrey A.I. Sitnik <andrey@sitnik.ru>"], + "description": "Wrapper for the Page Visibility API", + "license": "MIT", + "main": [ + "lib/visibility.core.js", + "lib/visibility.timers.js" + ], + "ignore": [ + "package.json", + "*.gemspec", + "Cakefile", + "test", + "*.rb", + ".*" + ] +} diff --git a/libs/bower_components/visibilityjs/index.js b/libs/bower_components/visibilityjs/index.js new file mode 100644 index 0000000000..2f43edb40b --- /dev/null +++ b/libs/bower_components/visibilityjs/index.js @@ -0,0 +1 @@ +module.exports = require('./lib/visibility.timers.js') diff --git a/libs/bower_components/visibilityjs/lib/visibility.core.js b/libs/bower_components/visibilityjs/lib/visibility.core.js new file mode 100644 index 0000000000..a87b0f7166 --- /dev/null +++ b/libs/bower_components/visibilityjs/lib/visibility.core.js @@ -0,0 +1,191 @@ +;(function (global) { + "use strict"; + + var lastId = -1; + + // Visibility.js allow you to know, that your web page is in the background + // tab and thus not visible to the user. This library is wrap under + // Page Visibility API. It fix problems with different vendor prefixes and + // add high-level useful functions. + var self = { + + // Call callback only when page become to visible for user or + // call it now if page is visible now or Page Visibility API + // doesn’t supported. + // + // Return false if API isn’t supported, true if page is already visible + // or listener ID (you can use it in `unbind` method) if page isn’t + // visible now. + // + // Visibility.onVisible(function () { + // startIntroAnimation(); + // }); + onVisible: function (callback) { + var support = self.isSupported(); + if ( !support || !self.hidden() ) { + callback(); + return support; + } + + var listener = self.change(function (e, state) { + if ( !self.hidden() ) { + self.unbind(listener); + callback(); + } + }); + return listener; + }, + + // Call callback when visibility will be changed. First argument for + // callback will be original event object, second will be visibility + // state name. + // + // Return listener ID to unbind listener by `unbind` method. + // + // If Page Visibility API doesn’t supported method will be return false + // and callback never will be called. + // + // Visibility.change(function(e, state) { + // Statistics.visibilityChange(state); + // }); + // + // It is just proxy to `visibilitychange` event, but use vendor prefix. + change: function (callback) { + if ( !self.isSupported() ) { + return false; + } + lastId += 1; + var number = lastId; + self._callbacks[number] = callback; + self._listen(); + return number; + }, + + // Remove `change` listener by it ID. + // + // var id = Visibility.change(function(e, state) { + // firstChangeCallback(); + // Visibility.unbind(id); + // }); + unbind: function (id) { + delete self._callbacks[id]; + }, + + // Call `callback` in any state, expect “prerender”. If current state + // is “prerender” it will wait until state will be changed. + // If Page Visibility API doesn’t supported, it will call `callback` + // immediately. + // + // Return false if API isn’t supported, true if page is already after + // prerendering or listener ID (you can use it in `unbind` method) + // if page is prerended now. + // + // Visibility.afterPrerendering(function () { + // Statistics.countVisitor(); + // }); + afterPrerendering: function (callback) { + var support = self.isSupported(); + var prerender = 'prerender'; + + if ( !support || prerender != self.state() ) { + callback(); + return support; + } + + var listener = self.change(function (e, state) { + if ( prerender != state ) { + self.unbind(listener); + callback(); + } + }); + return listener; + }, + + // Return true if page now isn’t visible to user. + // + // if ( !Visibility.hidden() ) { + // VideoPlayer.play(); + // } + // + // It is just proxy to `document.hidden`, but use vendor prefix. + hidden: function () { + return !!(self._doc.hidden || self._doc.webkitHidden); + }, + + // Return visibility state: 'visible', 'hidden' or 'prerender'. + // + // if ( 'prerender' == Visibility.state() ) { + // Statistics.pageIsPrerendering(); + // } + // + // Don’t use `Visibility.state()` to detect, is page visible, because + // visibility states can extend in next API versions. + // Use more simpler and general `Visibility.hidden()` for this cases. + // + // It is just proxy to `document.visibilityState`, but use + // vendor prefix. + state: function () { + return self._doc.visibilityState || + self._doc.webkitVisibilityState || + 'visible'; + }, + + // Return true if browser support Page Visibility API. + // + // if ( Visibility.isSupported() ) { + // Statistics.startTrackingVisibility(); + // Visibility.change(function(e, state)) { + // Statistics.trackVisibility(state); + // }); + // } + isSupported: function () { + return !!(self._doc.visibilityState || + self._doc.webkitVisibilityState); + }, + + // Link to document object to change it in tests. + _doc: document || {}, + + // Callbacks from `change` method, that wait visibility changes. + _callbacks: { }, + + // Listener for `visibilitychange` event. + _change: function(event) { + var state = self.state(); + + for ( var i in self._callbacks ) { + self._callbacks[i].call(self._doc, event, state); + } + }, + + // Set listener for `visibilitychange` event. + _listen: function () { + if ( self._init ) { + return; + } + + var event = 'visibilitychange'; + if ( self._doc.webkitVisibilityState ) { + event = 'webkit' + event; + } + + var listener = function () { + self._change.apply(self, arguments); + }; + if ( self._doc.addEventListener ) { + self._doc.addEventListener(event, listener); + } else { + self._doc.attachEvent(event, listener); + } + self._init = true; + } + + }; + + if ( typeof(module) != 'undefined' && module.exports ) { + module.exports = self; + } else { + global.Visibility = self; + } + +})(this); diff --git a/libs/bower_components/visibilityjs/lib/visibility.fallback.js b/libs/bower_components/visibilityjs/lib/visibility.fallback.js new file mode 100644 index 0000000000..4dcca2711d --- /dev/null +++ b/libs/bower_components/visibilityjs/lib/visibility.fallback.js @@ -0,0 +1,55 @@ +// Add Page Visibility API support to old browsers by focus/blur hack. +// +// Include this script _before_ Visibility.js. +// +// Note, that this hack doesn’t correctly emulate Page Visibility API: +// when user change focus from browser to another window (browser and your +// page may stay visible), this hack will decide, that you page is hidden. +// +// For Firefox 5–9 it will be better to use MozVisibility hack without +// this issue. See <https://github.com/private-face/mozvisibility>. +;(function (document) { + "use strict"; + + if ( document.visibilityState || document.webkitVisibilityState ) { + return; + } + + document.hidden = false; + document.visibilityState = 'visible'; + + var event = null + var i = 0 + var fireEvent = function () { + if( document.createEvent ) { + if ( !event ) { + event = document.createEvent('HTMLEvents'); + event.initEvent('visibilitychange', true, true); + } + document.dispatchEvent(event); + } else { + if ( typeof(Visibility) == 'object' ) { + Visibility._change.call(Visibility, { }); + } + } + } + + var onFocus = function () { + document.hidden = false; + document.visibilityState = 'visible'; + fireEvent(); + }; + var onBlur = function () { + document.hidden = true; + document.visibilityState = 'hidden'; + fireEvent(); + } + + if ( document.addEventListener ) { + window.addEventListener('focus', onFocus, true); + window.addEventListener('blur', onBlur, true); + } else { + document.attachEvent('onfocusin', onFocus); + document.attachEvent('onfocusout', onBlur); + } +})(document); diff --git a/libs/bower_components/visibilityjs/lib/visibility.js b/libs/bower_components/visibilityjs/lib/visibility.js new file mode 100644 index 0000000000..79f436d107 --- /dev/null +++ b/libs/bower_components/visibilityjs/lib/visibility.js @@ -0,0 +1,4 @@ +// File for Rails Assets Pipeline + +//= require visibility.core +//= require visibility.timers diff --git a/libs/bower_components/visibilityjs/lib/visibility.timers.js b/libs/bower_components/visibilityjs/lib/visibility.timers.js new file mode 100644 index 0000000000..76e53a16c3 --- /dev/null +++ b/libs/bower_components/visibilityjs/lib/visibility.timers.js @@ -0,0 +1,163 @@ +;(function (window) { + "use strict"; + + var lastTimer = -1; + + var install = function (Visibility) { + + // Run callback every `interval` milliseconds if page is visible and + // every `hiddenInterval` milliseconds if page is hidden. + // + // Visibility.every(60 * 1000, 5 * 60 * 1000, function () { + // checkNewMails(); + // }); + // + // You can skip `hiddenInterval` and callback will be called only if + // page is visible. + // + // Visibility.every(1000, function () { + // updateCountdown(); + // }); + // + // It is analog of `setInterval(callback, interval)` but use visibility + // state. + // + // It return timer ID, that you can use in `Visibility.stop(id)` to stop + // timer (`clearInterval` analog). + // Warning: timer ID is different from interval ID from `setInterval`, + // so don’t use it in `clearInterval`. + // + // On change state from hidden to visible timers will be execute. + Visibility.every = function (interval, hiddenInterval, callback) { + Visibility._time(); + + if ( !callback ) { + callback = hiddenInterval; + hiddenInterval = null; + } + + lastTimer += 1; + var number = lastTimer; + + Visibility._timers[number] = { + visible: interval, + hidden: hiddenInterval, + callback: callback + }; + Visibility._run(number, false); + + if ( Visibility.isSupported() ) { + Visibility._listen(); + } + return number; + }; + + // Stop timer from `every` method by it ID (`every` method return it). + // + // slideshow = Visibility.every(5 * 1000, function () { + // changeSlide(); + // }); + // $('.stopSlideshow').click(function () { + // Visibility.stop(slideshow); + // }); + Visibility.stop = function(id) { + if ( !Visibility._timers[id] ) { + return false; + } + Visibility._stop(id); + delete Visibility._timers[id]; + return true; + }; + + // Callbacks and intervals added by `every` method. + Visibility._timers = { }; + + // Initialize variables on page loading. + Visibility._time = function () { + if ( Visibility._timed ) { + return; + } + Visibility._timed = true; + Visibility._wasHidden = Visibility.hidden(); + + Visibility.change(function () { + Visibility._stopRun(); + Visibility._wasHidden = Visibility.hidden(); + }); + }; + + // Try to run timer from every method by it’s ID. It will be use + // `interval` or `hiddenInterval` depending on visibility state. + // If page is hidden and `hiddenInterval` is null, + // it will not run timer. + // + // Argument `runNow` say, that timers must be execute now too. + Visibility._run = function (id, runNow) { + var interval, + timer = Visibility._timers[id]; + + if ( Visibility.hidden() ) { + if ( null === timer.hidden ) { + return; + } + interval = timer.hidden; + } else { + interval = timer.visible; + } + + var runner = function () { + timer.last = new Date(); + timer.callback.call(window); + } + + if ( runNow ) { + var now = new Date(); + var last = now - timer.last ; + + if ( interval > last ) { + timer.delay = setTimeout(function () { + runner(); + timer.id = setInterval(runner, interval); + }, interval - last); + } else { + runner(); + timer.id = setInterval(runner, interval); + } + + } else { + timer.id = setInterval(runner, interval); + } + }; + + // Stop timer from `every` method by it’s ID. + Visibility._stop = function (id) { + var timer = Visibility._timers[id]; + clearInterval(timer.id); + clearTimeout(timer.delay); + delete timer.id; + delete timer.delay; + }; + + // Listener for `visibilitychange` event. + Visibility._stopRun = function (event) { + var isHidden = Visibility.hidden(), + wasHidden = Visibility._wasHidden; + + if ( (isHidden && !wasHidden) || (!isHidden && wasHidden) ) { + for ( var i in Visibility._timers ) { + Visibility._stop(i); + Visibility._run(i, !isHidden); + } + } + }; + + return Visibility; + } + + if ( typeof(module) != 'undefined' && module.exports ) { + module.exports = install(require('./visibility.core')); + } else { + install(window.Visibility) + } + +})(window); diff --git a/libs/bower_components/visibilityjs/logo.svg b/libs/bower_components/visibilityjs/logo.svg new file mode 100644 index 0000000000..6ee7babf47 --- /dev/null +++ b/libs/bower_components/visibilityjs/logo.svg @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="120px" width="100px" y="0px" x="0px" viewBox="0 0 100 120"> + <path d="M49.712,108.06c-7.041,0.438-23.017-13.789-31.736-29.328s-4.818-55.592-2.983-57.7,12.849-8.098,34.718-8.098,32.883,5.691,34.718,8.098,5.736,42.46-2.983,58-24.693,29.768-31.734,29.328z" stroke="#000" stroke-width="2" fill="#FFF"/> + <path d="M95.154,36.153s-8.494-7.602-18.972-7.602-18.972,7.602-18.972,7.602,8.494,7.743,18.972,7.743,18.972-7.743,18.972-7.743z" stroke="#600" stroke-width="2" fill="#FFF"/> + <path d="M95.284,36.008l0.161,0.144-0.159,0.145c-0.086,0.078-8.67,7.794-19.103,7.794s-19.017-7.716-19.103-7.794l-0.159-0.145,0.161-0.144c0.085-0.076,8.67-7.652,19.102-7.652,10.43,0,19.015,7.575,19.1,7.652zm-19.101,7.033c9.486,0,16.938-6.327,18.174-7.387-1.24-1.045-8.686-6.908-18.174-6.908-9.484,0-16.899,5.83-18.14,6.875,1.236,1.06,8.65,7.42,18.14,7.42z" stroke="#600" stroke-width="2" fill="#FFF"/> + <path d="M95.154,58.073s-8.494-7.602-18.972-7.602-18.972,7.602-18.972,7.602,8.494,7.743,18.972,7.743,18.972-7.743,18.972-7.743z" stroke="#600" stroke-width="2" fill="#FFF"/> + <path d="M95.284,57.928l0.161,0.144-0.159,0.145c-0.086,0.078-8.67,7.794-19.103,7.794s-19.017-7.716-19.103-7.794l-0.159-0.145,0.161-0.144c0.085-0.076,8.67-7.652,19.102-7.652,10.43,0,19.015,7.575,19.1,7.652zm-19.101,7.033c9.486,0,16.938-6.327,18.174-7.387-1.24-1.045-8.686-6.908-18.174-6.908-9.484,0-16.899,5.83-18.14,6.875,1.236,1.061,8.65,7.42,18.14,7.42z" stroke="#600" stroke-width="2" fill="#FFF"/> + <path d="M94.864,80.282s-8.494-7.602-18.972-7.602-18.972,7.602-18.972,7.602,8.494,7.743,18.972,7.743,18.972-7.743,18.972-7.743z" stroke="#600" stroke-width="2" fill="#FFF"/> + <path d="M94.994,80.136l0.161,0.144-0.159,0.145c-0.086,0.078-8.67,7.794-19.103,7.794s-19.017-7.716-19.103-7.794l-0.159-0.145,0.161-0.144c0.085-0.076,8.67-7.652,19.102-7.652,10.43,0.001,19.014,7.576,19.1,7.652zm-19.102,7.034c9.486,0,16.938-6.327,18.174-7.387-1.24-1.045-8.686-6.908-18.174-6.908-9.484,0-16.899,5.83-18.14,6.875,1.236,1.06,8.65,7.42,18.14,7.42z" stroke="#600" stroke-width="2" fill="#FFF"/> + <path d="M44.126,36.858s-8.858,7.691-19.785,7.691-19.786-7.691-19.786-7.691,8.858-7.691,19.785-7.691,19.786,7.691,19.786,7.691z" stroke="#600" stroke-width="2" fill="#FFF"/> + <circle cy="36.748" cx="24.34" r="6.861" fill="#600"/> + <circle cy="36.858" cx="24.34" r="3.523" fill="#FFF"/> + <path d="M44.126,58.398s-8.858,7.691-19.785,7.691-19.786-7.691-19.786-7.691,8.858-7.691,19.785-7.691,19.786,7.691,19.786,7.691z" stroke="#600" stroke-width="2" fill="#FFF"/> + <circle cy="58.287" cx="24.34" r="6.861" fill="#600"/> + <circle cy="58.398" cx="24.34" r="3.523" fill="#FFF"/> + <path d="M44.126,80.109s-8.858,7.691-19.785,7.691-19.786-7.691-19.786-7.691,8.858-7.691,19.785-7.691,19.786,7.691,19.786,7.691z" stroke="#600" stroke-width="2" fill="#FFF"/> + <circle cy="79.998" cx="24.34" r="6.861" fill="#600"/> + <circle cy="80.109" cx="24.34" r="3.523" fill="#FFF"/> +</svg> diff --git a/plugins/Live/Live.php b/plugins/Live/Live.php index ff5bb72985..aaddca1f22 100644 --- a/plugins/Live/Live.php +++ b/plugins/Live/Live.php @@ -38,6 +38,7 @@ class Live extends \Piwik\Plugin public function getJsFiles(&$jsFiles) { + $jsFiles[] = "libs/bower_components/visibilityjs/lib/visibility.core.js"; $jsFiles[] = "plugins/Live/javascripts/live.js"; $jsFiles[] = "plugins/Live/javascripts/visitorProfile.js"; $jsFiles[] = "plugins/Live/javascripts/visitorLog.js"; diff --git a/plugins/Live/javascripts/live.js b/plugins/Live/javascripts/live.js index 59913b8b02..17e08cded3 100644 --- a/plugins/Live/javascripts/live.js +++ b/plugins/Live/javascripts/live.js @@ -189,6 +189,14 @@ }, /** + * Return true in case widget is started. + * @returns {boolean} + */ + started: function() { + return this.isStarted; + }, + + /** * Set the interval for refresh * * @param {int} interval new interval for refresh @@ -207,6 +215,16 @@ $(function() { return; } + function scheduleAnotherRequest() + { + setTimeout(function () { refreshWidget(element, refreshAfterXSecs); }, refreshAfterXSecs * 1000); + } + + if (Visibility.hidden()) { + scheduleAnotherRequest(); + return; + } + var lastMinutes = $(element).attr('data-last-minutes') || 3, translations = JSON.parse($(element).attr('data-translations')); @@ -248,8 +266,7 @@ $(function() { ? translations['one_minute'] : translations['minutes'].replace('%s', lastMinutes); $(metrics[2]).text(lastMinutesText); - // schedule another request - setTimeout(function () { refreshWidget(element, refreshAfterXSecs); }, refreshAfterXSecs * 1000); + scheduleAnotherRequest(); }); ajaxRequest.send(true); }; @@ -280,3 +297,38 @@ function onClickPlay() { $('#pauseImage').show(); return $('#visitsLive').liveWidget('start'); } + +(function () { + if (!Visibility.isSupported()) { + return; + } + + var isStoppedByBlur = false; + + function isStarted() + { + return $('#visitsLive').liveWidget('started'); + } + + function onTabBlur() { + if (isStarted()) { + isStoppedByBlur = true; + onClickPause(); + } + } + + function onTabFocus() { + if (isStoppedByBlur && !isStarted()) { + isStoppedByBlur = false; + onClickPlay(); + } + } + + Visibility.change(function (event, state) { + if (Visibility.hidden()) { + onTabBlur(); + } else { + onTabFocus(); + } + }); +})();
\ No newline at end of file diff --git a/plugins/UserCountryMap/UserCountryMap.php b/plugins/UserCountryMap/UserCountryMap.php index dd14250800..9d124ecf97 100644 --- a/plugins/UserCountryMap/UserCountryMap.php +++ b/plugins/UserCountryMap/UserCountryMap.php @@ -61,6 +61,7 @@ class UserCountryMap extends \Piwik\Plugin public function getJsFiles(&$jsFiles) { + $jsFiles[] = "libs/bower_components/visibilityjs/lib/visibility.core.js"; $jsFiles[] = "plugins/UserCountryMap/javascripts/vendor/raphael.min.js"; $jsFiles[] = "plugins/UserCountryMap/javascripts/vendor/jquery.qtip.min.js"; $jsFiles[] = "plugins/UserCountryMap/javascripts/vendor/kartograph.min.js"; diff --git a/plugins/UserCountryMap/javascripts/realtime-map.js b/plugins/UserCountryMap/javascripts/realtime-map.js index 4a0b9e317a..5fe57e1790 100644 --- a/plugins/UserCountryMap/javascripts/realtime-map.js +++ b/plugins/UserCountryMap/javascripts/realtime-map.js @@ -478,6 +478,8 @@ if (firstRun && lastVisits.length) { // zoom changed, use cached report data gotNewReport(lastVisits.slice()); + } else if (Visibility.hidden()) { + nextReqTimer = setTimeout(refreshVisits, config.liveRefreshAfterMs); } else { // request API for new data $('.realTimeMap_overlay img').show(); |