Git Product home page Git Product logo

visibilityjs's Introduction

Visibility.js Build Status

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 either visible to a user or hidden in background tab or 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 still not 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 has an issue: when browser just lose focus but still visible for user, its state will change to [hidden]).

Sponsored by Evil Martians

Translations

Документация на русском: 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 smaller.

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:

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:

var minute = 60 * 1000;
Visibility.every(minute, 5 * minute, function () {
    checkForEmail();
});

When the page becomes visible, if the callback has not been called in longer than the visible interval, it will be called immediately. In the example above, if you hid the page for 9 minutes, checkForEmail will get called once while the page is hidden, and immediately when it is made visible.

Visibility.every returns a timer identifier, much like the setInterval function. However, it cannot be passed to clearInterval, and you should use Visibility.stop(id) to stop the timer.

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

Another common use case is when 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 some 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:

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 link.

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:

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:

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:

$(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):

$(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:

Visibility.change(function (e, state) {
    Statistics.visibilityChange(state);
});

Method change returns listener ID. You can use it to unbind listener by Visibility.unbind(id):

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.

var listener = Visibility.onVisible(function () {
    notification.takeAttention();
});

notification.onOutOfDate(function () {
    if ( typeof(listener) == 'number' ) {
        Visibility.unbind(listener);
    }
});

Packages

Visibility.js is shipped with 4 files:

  • visibility.core – core module.
  • visibility.timersevery and stop methods to set setInterval depend on visibility state.
  • visibilityvisibility.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.

Installing

Available by NPM:

npm install --save visibilityjs

Contributing

  1. To run tests you need node.js and npm. For example, in Ubuntu run:

    sudo apt-get install nodejs npm
  2. Next install npm dependencies:

    npm install
  3. Run all tests:

    npm test
  4. Also you can see real usage example in integration test test/integration.html.

visibilityjs's People

Contributors

ai avatar devstator82 avatar dmeremyanin avatar dominiq-eu avatar excaliburhan avatar jwadhams avatar kelonye avatar kimmobrunfeldt avatar lifenautjoe avatar maciejmrozinski avatar marayfirth avatar mcfedr avatar michaelgmcd avatar mikhailv avatar mponizil avatar runspired avatar termina1 avatar whitequark avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

visibilityjs's Issues

Give me one file that has all three

I need a single file visibility.min.js that has all the three components -- core, fallbacks and timer.

Better yet, why not just have a single file that has all the code?

On the downloads page the file visibility-0.X.X.min.js does NOT contain the fallback part.

stop() not working

I am running Visibility on Angular 1.5

It starts ok, but when i try to stop it, it just won't work.

if ($rootScope.hdRTimerId != undefined) Visibility.stop($rootScope.hdRTimerId);

This is how i am trying to stop it.

I am saving the id in the root scope so i don't lose it with page transitions, i won't have a problem because i am only using Visibility on 1 page, when i get back to the page, i try to run stop if the Id is set.

But it wont work and the callback is fired anyway :-(

Race condition on visibility change and Visibility.stop(timer) call in callback

I have following code on page for example:

var startTime = Date.now();
var timer = Visibility.every(1000, function() {
  // ... some code ...
  if (Date.now() - startTime > 5000) Visibility.stop(timer);
});

If I switch to another page before 5 sec will expire and after 5 sec will return back on the page, callback will be called and .stop(timer) as well, but every timer will still work and there is no way to stop it after that. This is because setInterval is calling after callback call:

Add library to bower/npm

Would be super helpful if this wonderful library was available for client-side package managers like bower or npm.

Doesn't work in Electron

Seems to be related to #30. I am also on OSX and Electron is Chrome-backed.

IMO not working on Electron is a serious draw-back given the popularity of the platform.

Bundle for Sprockets

#= require visibility.bundle

Instead of:

#= require mozvisibility
#= require visibility
#= require visibility.fallback

Add browserify compatibility

In order to use visibility.js with browserify, it needs to define a module.exports. An easy way to do this (and be compatible with other module systems) is to use universal module definition.

Ideally, visibility.js would also be available on npm for easy installation and package management. It looks like visibility is taken, but visibilityjs is still available.

Doesn't seem to work in chrome/mac?

Whatever I do (switching to other tabs, windows, programs or minimize the current window) it keeps counting up the seconds the page is visible for, It never detects that i'm leaving the page.

Mobile in-app WebView support

Does this API properly work when an in-app WebView is created and loaded off screen and then is brought into visibility on the device? Same thing for going back off screen.

Get event prior to going into state

I have a unique case where I must perform an operation prior to the state change. Is there a way to get a before_visibilityState the event, perform an action, then allow the visibilityState to change?

Host a live demo

Hi @ai , I loved the way of the library providing a comfortable way to apply visibility API.
And I loved the way how it versioning with historical spacecraft names.

Here I have a suggestion that: it may host a live demo (like what integration test test/integration.html did) in gh-pages branch and put a hyperlink on readme file, so that developers can take a sneak peek about how visibility.js works in real-case.

If you're agree with this suggestion, I think I am available for working on a PR for it.

how to not call visibility if i made fullscreen

So in my app, I have games and when I click play , what I do is call fullscreen code which starts the game in fullscreen mode.

Somewhere in my app, I have this piece of code:

this.visibility = Visibility.change((event, state) => {
                            switch (state) {
                                case 'visible':
                                    break;
                                case 'hidden':
                                    console.log("coming here ? ");
                                    break;
                            }
                        });

Now, this works fine for all cases except fullscreen. The thing I want is when fullscreen gets activated, I don't want it to call console.log("coming here ?"). I don't want it to do anything. Is this possible?

Vibisility change event not triggered when focus switched to different application

I have the following code:

        this.listener = Visibility.change(function (e, state) {
            console.debug("Visibility: " + Visibility.state());
        });

The change function is only triggered in Chrome Version 46.0.2490.86 (64-bit) (OSX) when I change tabs. If I switch to another application or take focus away from the page, e.g. to the developer tools, the event isn't triggered.

Error when concatenating scripts

I ran my static HTML site through the the ant build script https://github.com/h5bp/ant-build-script
And the resulting compressed assets threw an error.

I added a semi colon to the end of the file I got here http://cloud.github.com/downloads/ai/visibility.js/visibility-0.5.0.min.js ran the build script again and the resulting JS file worked.

Just wanted to raise this so lots of other people don't have to go around adding semi colons to their files.

Thanks for work.

typings

Hi,

I use your library in typescript as follows (working):

import * as V from 'visibilityjs'

V.every(1500, ...);

However, the typing is broken then. I think the following would be more correct (and fixes my type errors):

declare module 'visibilityjs' {
  export function every(interval: number, callback: Function);
  export function onVisible(callback: Function);
  export function afterPrerendering(callback: Function);
  export function isSupported(): boolean;
  export function state(): string;
  export function hidden(): boolean;
  export function unbind(callback: Function);
  export function change(listener: VisiblityChangeListener);
  export function stop(listener: VisiblityChangeListener);

  type VisiblityChangeListener = (event, state: string) => void;
}

Bug in Safari 5.1.3

When visibility.fallback.js is included before visibility.js, Visibility.every works incorrect in Safari. I found cause:

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.